簡直不敢相信WPS表格竟然出現這樣的低級錯誤,這樣大bug的生產力工具還敢用嗎?


這不是 WPS 的問題,Excel 也是一樣的。

&-->

問題的根源在於計算機對浮點數的表示有誤差,如果我們把小數精度改為 20 位小數,就可以看到實際值並不精確等於 0.04 (如下圖)。這時候如果需要判斷

  • 相等,判斷它們差在誤差範圍內,也就是絕對值小於正誤差
  • 小於,判斷被判值減參考值的差小於負誤差
  • 大於,判斷被判值減參考值的差大於正誤差

上面的原理就是:等於、大於、小於都可以轉成減法結果跟 0 的比較,現在就是把 0 變成一個正負誤差值,擴大比較範圍

&-->


補充一下,上午忘了 ROUND 函數了,這個函數可以按指定小數位數求精。不說廢話,直接上圖,應該看得明白

&-->


一、我剛才檢驗了,出題人描述的現象「在WPS表格里,ABS(0.96-0.92)&<0.04 這個判斷的結果是TRUE,你敢相信嗎?居然有這樣的bug!就是這麼神奇!ABS(1.96-1.92)&<0.04的結果是FALSE,又變正常了」,的確如同出題描述的這樣。

我測試的情況報告如下:

使用函數產生的結果數據如下:

0.96 0.92 TRUE
1.96 1.92 FALSE

調用快鍵ctrl-~,調出函數顯示狀態,顯示的內容如下:

0.96 0.92 =A1-B1&<0.04 1.96 1.92 =A2-B2&<0.04

兩者綜合的圖示如下:

&-->

二、再如excel2003乃至excel2019中也都有類似問題: excel有bug?為什麼會返回FALSE?

測試圖如下:

&-->

&-->

三、

以前我曾發現excel的某些數值計算函數也有這樣的bug,例如mod(n,d)函數,計算n除以d的餘數。有人指出:n/d的值超過2^27=134217728時會出錯(經檢驗,果然如此。有人講,當n超過268435455=2^28-1時就會報錯,這個說法可能不正確。參見注釋一),在這種情況下,用 公式=n - d*INT(n/d) 來取代MOD(n, d) 。

此外,Excel函數數值只支持15位,MOD(n, d) = n - d*INT(n/d),因為MOD函數的流程是浮點運算,內置了兩位小數位,所以第一參數數值超過13位會報錯。

這個錯誤在wps2019和excel2003中同時出現。excel2019中有改善。

注釋一:在excel2003中計算的結果複製在此:

________N _____d _____Mod(N,d) _____N/d N-d*INT(N/d)
268435456 1 #NUM! 268435456 0
268435456 1.99 #NUM! 134892188.9 1.879999995
268435456 2 #NUM! 134217728 0
268435456 2.01 0.220000028 133549978.1 0.220000029
268435456 2.1 1.299999989 127826407.6 1.299999982
268435456 3 1 89478485.33 1
268435456 5 1 53687091.2 1
268435456 25 6 10737418.24 6
268435456 175 156 1533916.891 156
268435456 1225 1206 219130.9845 1206
268435456 8575 3656 31304.42636 3656
268435456 60025 3656 4472.060908 3656
268435456 420175 363806 638.865844 363806
268435456 2941225 783981 91.26654914 783981
268435456 20588575 783981 13.03807845 783981
268435456 144120025 124315431 1.862582636 124315431
268435456 1008840175 268435456 0.266083234 268435456
268435456 7061881225 268435456 0.038011891 268435456
268435456 49433168575 268435456 0.00543027 268435456
268435456 3.46032E+11 268435456 0.000775753 268435456

以上所用到的公式,在excel2003中按ctrl~切換為公式顯示模式,得到的內容如下:

________N _____d _____Mod(N,d) _____N/d N-d*INT(N/d)
268435456 1 =MOD(A2,B2) =A2/B2 =A2-B2*INT(A2/B2)
268435456 1.99 =MOD(A3,B3) =A3/B3 =A3-B3*INT(A3/B3)
268435456 2 =MOD(A4,B4) =A4/B4 =A4-B4*INT(A4/B4)
268435456 2.01 =MOD(A5,B5) =A5/B5 =A5-B5*INT(A5/B5)
268435456 2.1 =MOD(A6,B6) =A6/B6 =A6-B6*INT(A6/B6)
268435456 3 =MOD(A7,B7) =A7/B7 =A7-B7*INT(A7/B7)
268435456 5 =MOD(A8,B8) =A8/B8 =A8-B8*INT(A8/B8)
268435456 =5*B8 =MOD(A9,B9) =A9/B9 =A9-B9*INT(A9/B9)
268435456 =7*B9 =MOD(A10,B10) =A10/B10 =A10-B10*INT(A10/B10)
268435456 =7*B10 =MOD(A11,B11) =A11/B11 =A11-B11*INT(A11/B11)
268435456 =7*B11 =MOD(A12,B12) =A12/B12 =A12-B12*INT(A12/B12)
268435456 =7*B12 =MOD(A13,B13) =A13/B13 =A13-B13*INT(A13/B13)
268435456 =7*B13 =MOD(A14,B14) =A14/B14 =A14-B14*INT(A14/B14)
268435456 =7*B14 =MOD(A15,B15) =A15/B15 =A15-B15*INT(A15/B15)
268435456 =7*B15 =MOD(A16,B16) =A16/B16 =A16-B16*INT(A16/B16)
268435456 =7*B16 =MOD(A17,B17) =A17/B17 =A17-B17*INT(A17/B17)
268435456 =7*B17 =MOD(A18,B18) =A18/B18 =A18-B18*INT(A18/B18)
268435456 =7*B18 =MOD(A19,B19) =A19/B19 =A19-B19*INT(A19/B19)
268435456 =7*B19 =MOD(A20,B20) =A20/B20 =A20-B20*INT(A20/B20)
268435456 =7*B20 =MOD(A21,B21) =A21/B21 =A21-B21*INT(A21/B21)

四、

其他的不足之處,甚至是很明顯、違反常規的基本原理的bug或稱為低級錯誤的問題,也會有。我們可以直面他,正視他,讓我們來研究、討論、解決問題。如果避諱和躲閃,或有懈怠、忽視或盲從的態度,將不能圓滿的解決問 。我願想,我們一起來努力解決這些問題。

願軟體開發者能夠儘快解決這些BUG,使用戶用得放心。這樣,軟體開發者顯得有擔當、有責任感,使人信任,敢於託付,願意託付。謝謝。 相信大家共同努力,一起發現和解決問題,我們所依託的工具,會越來越好。謝謝。

(我相信將來會出現大成的工具,規範、穩定、強力、靈活而又兼容。)

五、

我感覺,(excel或wps中的表格處理,屬於)數值計算軟體,其計算準確度所造成的風險大過於符號計算的軟體。(這種說法是我的個人淺見,需要從理論和實踐上進行深入研究和分析。如有不妥不足,請諒解,請批評指正。謝謝。)

我感覺,當今的計算機的數值處理體系的底層某些處理方式,可能還需要一些調整,才能滿足更精密的計算和表達的需要。或者那些符號計算軟體,如maple,mathematica,maxima等等,matlab也有符號計算工具箱,對這些問題進行了一些考慮吧。

這些軟體中,我比較看好mathematica,我曾經用這個軟體來製表和處理數據表。

以下摘引自一位答題者 張戎 :

符號計算有什麼用?好像擅長符號計算的軟體都不流行? - 張戎的回答 - 知乎https://www.zhihu.com/question/23827765/answer/956643020

{開源的符號計算工具可以考慮:Python 的 SymPy。可以參考之前寫的一份內容:張戎:用 Python 來研究數學 --- SymPy 符號工具包介紹}

以下摘自 百度百科-符號計算:

國際上最有代表性和最流行的通用符號計算軟體有:MACSYMA,REDUCE,mu-MATH,MAPLE,Mathematica,Matlab(註:有符號計算工具箱Mupad),Python(註:符號工具包SymPy)等


你這個問題如果完全按照你的操作,在Microsoft 365 中的Excel里也是這樣,如下圖所示:

&-->

出現這個問題是因為C列的0.04實際上不是0.04,只是顯示成了0.04,如果你把前三列數字小數位展開,就會發現,C列實際上是0.3999999999999999999,這樣它自然小於0.04

&-->

這是因為計算機特性導致Excel在進行小數運算的時候會有誤差,所以為了解決你這個問題,在使用Excel的時候要時刻注意round。

這個具體案例中,如下圖所示,如果你在C列的公式裡面加上了round,結果就會是正確的FALSE。(round公式的意思是四捨五入到第幾位,比如round(2.837,2)的意思就是把2.837四捨五入到小數點後第二位,則其答案為2.84。)

&-->

當然你也可以選擇在E列的公式中給C列的取值加上round,那麼達成的效果和在C列里加round是一樣的。如下圖所示:

&-->

綜上:

使用Excel進行運算的時候,請養成隨手round的習慣。


&-->

試了試,確實有題主說的問題

下面給出的內容全部省去了abs函數

&-->

&-->

WPS使用QT寫的,也就用C++寫的,那麼自己單獨用C++寫出來這個會怎麼樣?

&-->

編譯運行一下:

&-->

結果和wps中計算的一樣(1是true,0是false)

很顯然就是浮點小數計算裡面的坑

如何解決?

只要使用ROUND函數就可以了,

&-->

&-->

按其他答主的回答來看,excel中不少版本也有此問題.

所以為了完美的解決這個問題,還是用ROUND函數設置計算精讀比較好.


這個涉及到浮點數運算的精度和誤差問題,這些數字用二進位是無法準確表示的,會有一定的誤差。這個是計算機原理決定的。但像python的decimal庫,可以轉化為十進位去運算,速度慢點,但可以實現十進位的精確計算。

不過話又說回來,計算機認為二進位才是正統,人認為十進位才是自然。有誤差沒啥大驚小怪的。


這個bug在你腦子裡。


計算機浮點運算存在誤差很正常吧。不要老拿WPS說事兒。


這種問題仔細想想就能知道。。

計算機本來就不能精確地儲存小數。

隨便舉個例子, 正方形的對角線的長度怎麼儲存?

用有限的內存怎麼儲存一個無限無規律的小數?

請把a&

請把a&>b改成a-b&>1e-6

請把a==b改成abs(a-b)&<1e-6

這裡1e-6是常用精度, 具體精度按照需求調整


數值計算的問題, 怎麼能責怪到wps上呢

&-->
JavaScript

&-->
C

&-->
python

&-->
php

&-->
java

這些知名的編程語言都無法準確判斷0.96-0.92與0.04的大小, 你現在相信這不是bug了嗎


在單元格里輸入 =(0.96-0.92)=(1.96-1.92)

結果是FALSE,不相等,WTF?!


推薦閱讀:

TAG:WPSOffice | Office文檔 | 生產力工具 |