2011-05-12 60 views
1

我知道有很多像這樣的問題,但我找不到我的答案。一些浮點精度和數值限制問題

  • 根據PC ASM:投票結束(前請仔細閱讀。
The numeric coprocessor has eight floating point registers. 
Each register holds 80 bits of data. 
Floating point numbers are always stored as 80-bit 
extended precision numbers in these registers.

這怎麼可能,當sizeof顯示不同的東西。例如,在x64架構的情況下,sizeof double是8這是遠離80bits。

  • 爲什麼std::numeric_limits< long double >::max()給我1.18973e+4932?!這是huuuuuuuuuge號碼。如果這不是獲得浮點數的最大值的方法,那麼爲什麼會編譯,甚至更多 - 爲什麼這會返回一個值。

  • 這是什麼意思:

Double precision magnitudes can range from approximately 10^−308 to 10^308

這些龐大的數字,你不能把它們存儲到8B甚至16B(這是擴展精度,這是隻有128位)?

顯然,我錯過了一些東西。其實很明顯,很多東西。

+0

刪除了「C」標籤。 – 2011-05-12 16:29:32

+0

閱讀時間'每個計算機科學家應該知道什麼關於浮點運算' – 2011-05-12 16:31:28

+0

那麼,只有'std :: numeric_limits'用於C++,而不是C.其他的東西都是相同的 - 討論'float',雙'和'長雙',對吧? – 2011-05-12 16:32:17

回答

4

1)sizeof是內存中的大小,而不是寄存器中的大小。 sizeof以字節爲單位,所以8個字節= 64位。當內存中計算雙精度時(在這個架構上),它們會得到額外的16位,用於更精確的中間計算。當該值被複制回內存時,額外的16位會丟失。

2)爲什麼你認爲long double不會達到1.18973e + 4932?

3)爲什麼你不能在8字節存儲10^308?我只需要13位:4來存儲10,和9至存儲308

+0

哈,真好!用於解釋'3)'的+1。我沒有想過這個。我的計算是:'2^64 - 1' – 2011-05-12 16:54:31

0

FPU使用的空間大小和內存中用於表示double的空間大小是兩回事。 IEEE 754(可能是大多數體系結構使用的)指定32位單精度和64位雙精度數,這就是爲什麼sizeof(double)爲您提供8個字節。 Intel x86在內部使用80位進行浮點數學運算。

std::numeric_limits< long double >::max()給你正確的大小long double它通常是80位。如果你想把64位的最大尺寸加倍,你應該使用它作爲模板參數。

對於有關範圍的問題,爲什麼你認爲你不能以8字節存儲它們?他們確實實際上是合適的,而你所缺少的是,在範圍的極端有一些無法表示的數字(例如指數接近308,有許多整數不能被表示出來)。

另請參閱http://floating-point-gui.de/瞭解有關浮點的信息。

1
  1. double一個不是英特爾協處理器80位浮點,它是一個IEEE 754的64位浮點。隨着sizeof(雙)你會得到後者的大小。

  2. 這是獲得long double的最大值的正確方法,所以你的問題是毫無意義的。

  3. 您可能會錯過浮點數不是確切的數字。 10^308不存儲308位數字,只有大約19位數字。

0

計算機上的浮點數是根據IEEE 754-2008來表示的。

它定義幾種格式,除其
binary32 =單精度,
binary64 =雙精度和
binary128 =四倍精度是最常見的。
http://en.wikipedia.org/wiki/IEEE_754-2008#Basic_formats

雙精度數字有52位數字,它給出了精度,10位指數,這給出了數字的大小。
所以雙打1.xxx(52二進制位)* 2 ^指數(10成二進制數位,所以達到2^10 = 1024)

到2^1024 = 1.79 * 10^308
哪這就是爲什麼這是雙倍存儲的最大價值。

當使用四倍精度數,它們的精度112位和14位指數,所以最大指數爲16384。

作爲2^16384給出1,18- * 10^4932你看到你的C++測試是完全正確的,在x64上你的double實際上存儲在一個四倍精度數字中。