我有一个double
打印的 as0.000000
并且我试图将它与 进行比较0.0f
,但没有成功。为什么这里有区别?确定您的双倍是否为零的最可靠方法是什么?
问问题
12731 次
4 回答
20
要确定它是否足够接近零以使其打印0.000000
到小数点后六位,例如:
fabs(d) < 0.0000005
不过,处理浮点计算中的小错误通常会变得相当复杂。
如果您想更好地了解您所获得的价值,请尝试使用%g
而不是%f
.
于 2011-08-10T09:38:52.050 回答
4
你可以做一个范围。比如 -0.00001 <= x <= 0.00001
于 2011-08-10T09:39:47.697 回答
4
这是现代计算机上浮点运算的基本问题。它们本质上是不精确的,无法可靠地进行比较。例如,语言 ML 明确禁止对真实类型进行相等比较,因为它被认为太不安全。另请参阅 David Goldberg 关于此主题的出色(如果有点长且面向数学)论文。
编辑:tl;博士:你可能做错了。
于 2011-08-10T09:40:02.563 回答
1
此外,浮点数的一个经常被忽视的特征是非规范化数。这是具有最小指数的数字,但不适合 0.5-1 范围。
这些数字低于浮点数的 FLT_MIN 和双精度数的 DBL_MIN。
使用阈值的一个常见错误是比较两个值,或使用 FLT_MIN/DBL_MIN 作为限制。
例如,这会导致不合逻辑的结果(如果您不了解非规范化):
bool areDifferent(float a, float b) {
if (a == b) return false; // Or also: if ((a - b) == FLT_MIN)
return true;
}
// What is the output of areDifferent(val, val + FLT_MIN * 0.5f) ?
// true, not false, even if adding half the "minimum value".
非规范化通常还意味着计算中的性能损失。但是,您不能禁用它们,否则此类代码仍可能产生除以零浮点异常(如果启用):
float getInverse(float a, float b) {
if (a != b)
return 1.0f / (a-b); // With denormals disabled, a != b can be true, but (a - b) can still be denormals, it'll rounded to 0 and throw the exception
return FLT_MAX;
}
于 2013-11-26T11:21:40.833 回答