一些浮点精度和数值限制问题

时间:2011-05-12 16:21:38

标签: c++ floating-point limit

我知道有很多像这样的问题,但我找不到答案。投票结束前请阅读(:

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架构上,size double为8,远离80位。

  • 为什么std::numeric_limits< long double >::max()会给我1.18973e+4932?这是huuuuuuuuuuge号码。如果这不是获得最大浮点数的方法,那么为什么这会编译,甚至更多 - 为什么这会返回一个值。

  • 这是什么意思:

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

这些是巨大的数字,你不能将它们存储到8B甚至16B(扩展精度只有128位)?

显然,我错过了一些东西。实际上,显然,很多事情。

4 个答案:

答案 0 :(得分:4)

1)sizeof是内存中的大小,而不是寄存器中的大小。 sizeof以字节为单位,因此8字节= 64位。当在存储器中计算双精度时(在该架构上),它们获得额外的16位以进行更精确的中间计算。将值复制回内存时,额外的16位将丢失。

2)为什么你认为long double没有达到1.18973e + 4932?

3)为什么不能以8个字节存储10 ^ 308?我只需要13位:4位存储10位,9位存储308位。

答案 1 :(得分:1)

  1. A double不是英特尔协处理器80位浮点,它是IEEE 754 64位浮点。使用sizeof(double),您将获得后者的大小。

  2. 这是获取long double最大值的正确方法,因此您的问题毫无意义。

  3. 您可能错过了浮点数不是确切的数字。 10 ^ 308不存储308个数字,仅存储约19个数字。

答案 2 :(得分: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/

答案 3 :(得分: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上,您的双倍实际存储在四倍精度数中。