2011-05-12 82 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实际上存储在一个四倍精度数字中。