如果可以用IEEE 754中的二进制格式表示硬编码是否精确浮动?

例如,0,0.5,0.15625,1,2,3 ……是从IEEE 754转换而来的值。它们的硬编码版本是否精确?

例如:

float a=0; if(a==0){ return true; } 

总是回归真实? 其他例子:

 float a=0.5; float b=0.25; float c=0.125; 

a * b总是等于0.125而a * b == c总是如此? 还有一个例子:

 int a=123; float b=0.5; 

a * b总是61.5? 或者一般来说,整数乘以IEEE 754二进制浮点精确?

或者更一般的问题:如果值是硬编码,并且值和结果都可以用IEEE 754中的二进制格式表示(例如:0.5 – 0.125),那么值是否准确?

浮点数没有固有的模糊性。 只是有些(但不是全部)实数无法准确表示。

比较固定宽度的十进制表示,比方说三位数。 可以使用1.00表示整数1,并且可以使用0.10表示1/10,但是只能使用0.33来近似1/3。

如果我们改为使用二进制数字,则整数1表示为1.00(二进制数字),1/2表示为0.10,1 / 4表示为0.01,但1/3可以(再次)仅表示近似值。

但有些事情需要记住:

  • 它与十进制数字的数字不同。 1/10可以使用十进制数字精确地写为0.1,但不使用二进制数字,无论您使用多少(无穷大)。
  • 实际上,很难跟踪哪些数字可以
    代表哪些不可以。 0.5可以,但0.4不能。 因此,当您需要确切的数字时,例如(通常)在使用金钱时,您不应该使用浮点数。
  • 根据一些消息来源,一些处理器在对无法准确表示的数字执行浮点计算时会在内部做出奇怪的事情,从而导致结果以实际上不可预测的方式变化。

(我的观点是,它实际上是一个合理的第一近似值,是的,浮点数本身就是模糊的,所以除非你确定你的特定应用程序可以处理它,所以远离它们。)

有关您可能需要或想要的更多详细信息,请阅读着名的每个计算机科学家应该知道的关于浮点运算的内容 。 此外,这个更易于访问的网站: 浮点指南 。

不,但正如Thomas Padron-McCarthy所说,有些数字可以使用二进制来精确表示,但并非所有数字都可以。

这是我向与我合作的非开发人员解释的方式(如Mahmut Ali,我也在一个非常古老的金融包上工作):想象一下,有一个非常大的蛋糕切成256片。 现在你可以给1个人整个蛋糕,2个人一半切片,但很快你决定将它分成3个你不能 – 它是85或86 – 你不能再分开蛋糕了。 浮点数也是如此。 您只能在某些表示中获得确切的数字 – 有些数字只能近似得到。

C ++不需要二进制浮点表示。 内置整数需要具有二进制表示,通常是二进制补码,但也支持一个补码,符号和幅度。 但浮点可以是例如十进制。

这就留下了一个问题:C ++浮点是否可以有一个不具有2作为素数因子的基数,如2和10.是否允许其他基数? 我不知道,上次我试图检查,我失败了。

但是, 假设基数必须是2或10,那么所有示例都涉及2的幂的值,因此可以精确表示。

这意味着对大多数问题的单一回答是“是”。 唯一的例外是“整数乘以IEEE 754二进制浮点数[精确]”。 如果结果超出了可用的精度,那么它可能不准确,但不是这样。

有关浮点表示和属性的背景信息,请参阅经典的“每个计算机科学家应该知道的关于浮点算术的内容” 。


如果一个值可以在32位或64位IEEE 754中精确表示,那么这并不意味着它可以用其他浮点表示精确表示。 这是因为不同的32位表示和不同的64位表示使用不同的位数来保持尾数并具有不同的指数范围。 因此,可以以一种方式精确表示的数字可以超出某些其他表示的精度或范围。


您可以使用std::numeric_limits::is_iec559 (例如Tdouble )来检查您的实现是否声称与IEEE 754兼容。 但是,当打开浮点优化时,至少g ++编译器(1)错误地声称是IEEE 754,而不是根据该标准正确处理例如NaN值。 实际上, is_iec559只告诉您数字表示是否是IEEE 754,而不是语义是否符合。


(1)基本上,gcc和g ++不是为不同的语义提供不同的类型 ,而是尝试通过编译器选项来适应不同的语义。 并且对程序的各个部分进行单独编译,这些编译不符合C ++标准。

原则上,这应该是可能的。 如果你将自己限制在具有有限2次幂表示的这类数字中。

但这很危险:如果有人.0625你的代码并将你的0.50.4或你的.0625更改0.5 .0625怎么办呢? 那你的代码就坏了。 不,即使是过多的评论也无济于事 – 有人会永远忽略它们。