C++ 浮点计算和舍入

C++ 浮点计算和舍入,c++,floating-point,cpu,rounding,C++,Floating Point,Cpu,Rounding,我想我在某个地方读到过cpu的“在50位中做一些浮点计算,这样它们就可以正确地四舍五入到32位”。我认为这意味着在前面提到的浮点运算中计算的中间值是以50位计算的,这样就可以实现“到浮点大小的正确舍入” 这句话是什么意思?这是真的吗?如果是这样的话,你能告诉我一些资源,解释为什么他们需要计算18个额外的位吗?为什么不是19岁或17岁?还是这完全是假的 编辑:-我发现这个链接非常有帮助而且详尽 谢谢这与ε值有关。以经典的0.1+0.2问题为例: 在大多数语言中,0.1+0.2!=0.3. 这是因为

我想我在某个地方读到过cpu的“在50位中做一些浮点计算,这样它们就可以正确地四舍五入到32位”。我认为这意味着在前面提到的浮点运算中计算的中间值是以50位计算的,这样就可以实现“到浮点大小的正确舍入”

这句话是什么意思?这是真的吗?如果是这样的话,你能告诉我一些资源,解释为什么他们需要计算18个额外的位吗?为什么不是19岁或17岁?还是这完全是假的


编辑:-我发现这个链接非常有帮助而且详尽


谢谢

这与ε值有关。以经典的0.1+0.2问题为例:

在大多数语言中,0.1+0.2!=0.3. 这是因为0.1和0.2是以10为底的终止小数,而以2为底的0.1看起来像0.000110011。。。0.2看起来像0.001100110011。。。这意味着当你把这两个值加在一起,你会得到一个重复的二进制数,当你得到无限精度时,它会接近0.3,类似于 0.333333333... + 0.33333333.... 随着精度越来越高,接近2/3


至于为什么18个额外比特和19个额外比特,这是一个更复杂的讨论。有关更多详细信息,请参阅。

这与ε值有关。以经典的0.1+0.2问题为例:

在大多数语言中,0.1+0.2!=0.3. 这是因为0.1和0.2是以10为底的终止小数,而以2为底的0.1看起来像0.000110011。。。0.2看起来像0.001100110011。。。这意味着当你把这两个值加在一起,你会得到一个重复的二进制数,当你得到无限精度时,它会接近0.3,类似于 0.333333333... + 0.33333333.... 随着精度越来越高,接近2/3


至于为什么18个额外比特和19个额外比特,这是一个更复杂的讨论。请参阅以了解更多详细信息。

我无法保证这一点,但我猜您实际遇到的是53位,而不是50位。他们之所以使用53位,是因为这是浮点类型的下一个标准大小。在IEEE 754标准中,最小的类型为32位。下一个大小是总共64位,它有一个53位的有效位(也称尾数)。因为他们已经有了专门处理该大小的硬件,所以(在大多数情况下)以该大小进行计算,然后舍入到较小的大小可能是最简单的。

我不能以任何方式保证,但我猜您遇到的实际上是53位,而不是50位。他们之所以使用53位,是因为这是浮点类型的下一个标准大小。在IEEE 754标准中,最小的类型为32位。下一个大小是总共64位,它有一个53位的有效位(也称尾数)。因为他们已经有了专门处理该大小的硬件,所以(在大多数情况下)以该大小进行计算,然后舍入到较小的大小可能是最容易的。

在现代计算机上,以双精度(1个符号位、11个指数位、52个显式有效位)进行计算是很常见的与单精度计算(1个符号位、8个指数位、23个有效位)一样快。因此,当加载浮点对象、计算和存储浮点对象时,编译器可能会将浮点值加载到双精度寄存器、以双精度计算和存储单精度结果。这将以极低的成本提供额外的精度,从而为您带来好处。结果可能更经常“正确舍入”(返回的结果是最接近数学精确结果的可表示值),但这并不能保证(因为仍然存在舍入误差,这可能会以意外方式相互作用),或者可能更精确(比浮点计算更接近精确结果)(但这也不能保证),但在极少数情况下,双精度计算可能会返回比单精度计算更糟糕的结果

有时双精度比单精度更昂贵,尤其是在执行SIMD编程时

通常,高级语言让编译器自由决定如何计算浮点表达式,因此编译器可能使用单精度或双精度,具体取决于供应商的选择(或编译器的质量)、传递给编译器的优化和目标开关,以及编译代码的其他方面(例如,在中进行计算的计算机寄存器的可用性)以及其他出于实际目的可能是随机的因素。因此,这不是您可以依赖的行为


您所听到的另一个含义可能是,单精度函数的库例程(如sinf或logf)可以用双精度编写,这样比完全用单精度编写更容易获得所需的结果。这是常见的。但是,这样的库例程是由e分析计算过程中可能出现的错误的专家,因此这不仅仅是假设更多位会产生更好的结果。

在现代计算机上,双精度计算(1个符号位、11个指数位、52个显式有效位)与单精度计算一样快是很常见的(1个符号位,8个指数位,23个有效位)。因此,当您加载浮点对象、计算和存储浮点对象时,编译器可能会将浮点值加载到双精度寄存器中,以双精度进行计算,并存储单精度结果。这通过以很少的成本提供额外精度而使您受益。结果可能更经常“正确舍入”(返回的结果是最接近数学精确结果的可表示值),但这并不能保证(因为仍然存在舍入误差,这可能会以意外的方式相互作用),或者可能更精确(比floa更接近精确结果)