1/3+1/6=計算機是如何得出0.5的?

兩個無限循環小數相加,運算器是如何處理的?


首先,雖然1/3和1/6都是無限循環小數,但在CPU里,位數都是有限的,參見:浮點數_百度百科,英語好的可以看Single-precision floating-point format

所以實際上1/3和1/6在內存里不是長度無限的,具體來說,以gcc 481作為測試環境的話,大概是這樣的:

1/3在內存里是0x3eaaaaab
1/6在內存里是0x3E2AAAAB

這兩個數字如果換算成十進位小數,那麼應該是:

1/3 =&> 0.3333333432674407958984375
1/6 =&> 0.16666667163372039794921875

也就是說,這兩個數本身在內存就是不精確的。

因為計算機內部都是二進位的,這兩個數值用二進位表示是這樣的:

1/3 =&> 0.01010101010101010101011
1/6 =&> 0.001010101010101010101011

現在計算機做浮點都是硬浮點,那麼具體的計算過程都是由CPU來完成的。

1/3+1/6 = 0.01010101010101010101011 + 0.001010101010101010101011

具體過程:

0.010101010101010101010110
+ 0.001010101010101010101011
--------------------------------
0.100000000000000000000001

因為這個時候精度已經多出一位了,此時CPU要做一個取捨,根據Intel的手冊(參見這裡浮點處理和指令編碼(更新完畢))

(註:實際CPU未必是這種位對齊的演算法,具體要看硬體實現)

這種情況下,最後的位數是01默認是舍掉的。

所以最終的結果就是0.10000000000000000000000,這個數字正好就是十進位的0.5

具體二進位十進位轉換過程可以參考一下:十進位轉二進位

參考代碼:

#include &
#include &
int main()
{
float x = 1.0/3, y = 1.0/6;
unsigned int a, b;
memcpy(a, x, sizeof(a));
memcpy(b, y, sizeof(b));
printf("%.100f %.100f %.100f
", x, y, x + y);
printf("%x %x
", a, b);
return 0;
}


用浮點數的話,IEEE 754 格式 1/3 + 1/6 的結果經過舍入能得到精確的 1/2。

有些語言和庫提供精確的「有理數」類型,可以精確地進行分數計算。


在支持有理數的環境, 就和人算分數一樣

Ruby:

[1] pry(main)&> require "mathn"
=&> true
[2] pry(main)&> 1/3 + 1/6
=&> (1/2)

Julia:

julia&> 1//3 + 1//6
1//2


看是什麼環境,

普通數值計算就是浮點數相加,近似回十進位。

如果是mathematica等數學計算就要識別分數,約分,相加再約分。


我覺得很明顯,計算機小數和分數是分開算得,0.5000000000001和1/2完全不同


樓上說的通分有道理,在windows中的計算器程序,就將1/3儲存為三分之一而不儲存為0.333333……藉此提高了計算的精確性


腦部電腦看見1/3和2/6卻不認識


我想:默認環境下,乘法器進行位移相加先把分數變成小數,對於我們認為的分數,計算機看來跟除法運算沒有差別,然後加法器對兩個處理過後的分數做加法,輸出結果。

有特殊要求的,可使用專門指令處理相應數字,譬如精度等


1/3=0.3333333333333

1/6=0.1666666666667

加起來等於0.5

計算機就是這樣處理的,精度一般是2的26次方分之一,也達不到100%精準,只能儘可能靠近


難道不是把1/3換成2/6 再相加么-_-||


可能是因為這個算成二進位再轉為十進位之後非常接近0.5了,題主可以試試0.1+0.2


如果換成(1除以3)+(1除以6)它就不等於0.5而是0了


手機裡面0.333333333+0.666666666=1


在程序的背後可能會是一個有理數類,其中分子分母分別用整數表示。


推薦閱讀:

為什麼201X年還有很多學計算機的不知道C99規範起可以在調用函數時用&傳引用?
適用於個人用戶的最佳數據備份方案有哪些?
學習知識的時候系統學習的利弊?
二進位是如何將加減乘除變換為加法實現的?加法是如何由邏輯運算與、或、異或來實現的?
決定論可以被證偽嗎?

TAG:演算法 | 計算機 | 計算機原理 | CPU設計 |