繁体   English   中英

常量赋值的浮点比较

[英]Floating-point comparison of constant assignment

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

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(xy)<epsilon 是否有可能在分配中引入错误? 我太偏执了吗?

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

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

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

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

换句话说,如果该值是完全表示(和1 ,在IEEE754,正如100在静态投),你得到的价值。 否则(例如0.1 )你得到一个实现定义的紧密匹配(a) 现在我非常担心基于相同输入令牌选择不同的紧密匹配的实现,但这可能的。


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

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

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

不,如果你指定文字他们应该是相同的:)

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

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

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

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

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

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

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

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

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

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

第一个例外:

0.0 == -0.0

存在负零,其与IEEE 754标准相比相等。 这意味着1 / INFINITY == 1 / -INFINITY打破f(x)== f(y)=> x == y

第二个例外:

NaN!= NaN

这是NotaNumber的一个特殊警告,它允许在没有可用测试功能的系统上找出数字是否为NaN(是,发生这种情况)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM