常量赋值的浮点比较

时间:2012-03-23 04:45:58

标签: c++ floating-point floating-point-precision

比较双精度是否相等时,我们需要给出容差级别,因为浮点计算可能会引入错误。例如:

double x; 
double y; 
x = f();
y = g();

if (fabs(x-y)<epsilon) {
   // they are equal!
} else {
   // they are not!
}

但是,如果我只是分配一个常量值而不进行任何计算,我还需要检查epsilon吗?

double x = 1;
double y = 1;

if (x==y) {
   // they are equal!
} else {
   // no they are not!
}

==比较是否足够好?或者我需要再次fabs(x-y)<epsilon?是否有可能在分配中引入错误?我太偏执了吗?

如何投射(double x = static_cast<double>(100))?这会引入浮点错误吗?

我在Linux上使用C ++,但如果它因语言而异,我也想了解它。

5 个答案:

答案 0 :(得分:3)

实际上,它取决于价值和实施。 C ++标准(草案n3126)在2.14.4 Floating literals

中有这个说法
  

如果缩放值在其类型的可表示值范围内,则结果为缩放值(如果可表示),否则最大或更小的可表示值最接近缩放值,以实现定义的方式选择。

换句话说,如果值完全可以表示(并且1是,在IEEE754中,与静态强制转换中的100一样),则获得该值。否则(例如使用0.1),您将获得实现定义的紧密匹配(a)。现在我非常担心基于相同输入令牌选择不同紧密匹配的实现,但 可能。


(a)实际上,该段落可以通过两种方式阅读,要么实现可以自由选择最接近的较高值或最接近的较低值,无论哪个实际上最接近,或者必须选择最接近所需值的值。

如果是后者,它不会改变这个答案,因为你所要做的只是在两个可表示类型的中点处硬编码浮点值,并且实现再次可以自由选择。

例如,它可能会在下一个较高和下一个较低之间交替出于同样的原因应用银行家的舍入 - 以减少累积错误。

答案 1 :(得分:0)

否如果您指定文字,则它们应该相同:)

此外,如果您从相同的值开始并执行相同的操作,它们应该是相同的。

浮点值不精确,但操作应产生一致的结果:)

答案 2 :(得分:0)

这两种情况最终都要经过实施定义的陈述。

浮点值的存储及其表示形式可以采用地址或常量加载?通过快速数学优化?寄存器宽度是多少?它存储在SSE寄存器中吗?存在许多变化。

如果您需要精确的行为和可移植性,请不要依赖此实现定义的行为。

答案 3 :(得分:0)

IEEE-754是浮点数的标准常见实现,它需要浮点运算来产生一个结果,该结果是无限精确结果的最接近的可表示值。因此,您将面临的唯一不精确是在执行每个操作后进行舍入,以及从链中较早执行的操作中传播舍入误差。浮动本身并不精确。顺便说一句,epsilon可以而且应该被计算出来,你可以参考任何数字书。

浮点数可以精确表示整数到尾数的整数。因此,例如,如果从int转换为double,它将始终是精确的,但是对于转换为float,对于非常大的整数,它将不再是精确的。

有一个主要的例子,广泛使用浮点数作为整数的替代,它是LUA脚本语言,没有整数内置类型,浮点数广泛用于逻辑和流量控制等使用浮点数的性能和存储损失小于在运行时解析多种类型的代价,并使实现更轻。 LUA不仅广泛用于PC,还广泛用于游戏机。

现在,许多编译器都有一个可选的开关,可以禁用IEEE-754的兼容性。然后做出妥协。非规范化数字(非常小的数字,其中指数达到最小可能值)通常被视为零,并且可以在幂,对数,sqrt和1 /(x ^ 2)的实现中进行近似,但是加/减,比较和乘法应保留其可以精确表示的数字的属性。

答案 4 :(得分:0)

答案很简单:对于常量==没问题。 您应该注意两个例外:

第一个例外:

0.0 == -0.0

对于IEEE 754标准,存在负零,相等。这意味着 1 / INFINITY == 1 / -INFINITY,它打破f(x)== f(y)=&gt; x == y

第二个例外:

NaN!= NaN

这是NotaNumber的特殊警告,它允许查明数字是否为NaN 在没有测试功能的系统上(是的,会发生这种情况)。