与具有浮点值的 0.0 进行比较
Comparison to 0.0 with floating point values
使用浮点数时,有时会出现舍入问题。因此,通常不建议将计算结果与 == 或 != 进行比较,而是使用适当的界限,如 abs(a-b)<1.0e-10
.
但是用它来比较 0.0
合适吗?
这就是我所说的:
double foo(){
//code which can return values that aren't 0.0
//all returns are either literals or global variables defined with literals
return 0.0;
}
此处 f
将始终 return 恰好 0.0
或明确不是 0.0
的数字。具体来说,这些数字的大小都将大于 0.1
但小于 2.0
.
如果 return 是 0.0
,0.0==foo()
会一直是 true
吗?如果 foo
return 是 0.0
以外的值,0.0==foo()
是否有可能成为 true
?
最多 std::numeric_limits::digits<float>
你是安全的。这是因为尾数是整数类型(通常是特定于平台的 uint;然后通过符号位和指数扩展为浮点数)。
http://en.cppreference.com/w/cpp/types/numeric_limits/digits
如果你 return 一个文字 0.0
那么是的,但这通常不是一个好主意,因为虽然今天是这样,但你能确定在维护或代码重用下它会保持真实。最好编写一些可以在更广泛的环境中工作的代码。在这种情况下:
foo() < 0.1
对于您指定的所有值, 将 return 为假。更通用的解决方案是测试是否足够接近零:
static const EPSILON = 0.00001 ;
std::fabs( foo() - 0.0 ) < EPSILON ;
最好使用上述模式之一,因为它不需要foo()
对"zero"的精度做出任何保证。
在你的情况下使用浮点相等是完全正确的== 0.0
。
它完全符合函数的意图(return 某个值,如果失败则为 0.0)。使用任何其他 epsilon 在某种程度上是任意的,并且需要了解正确值的范围。如果有什么事情发生变化,很可能是值的范围而不是 0,所以测试 == 0.0
与 IMO 的其他解决方案相比不亚于未来的证明。
我看到的唯一问题是一些编译器会警告相等性 (-Wfloat-equal) 的可疑使用...这与警告 int a,b,c; ...; c=a+b;
一样有用,因为这样的指令可能会导致问题 (整数溢出和未定义的行为)。奇怪的是,我从来没有看到第二个警告。
因此,如果您想使用 -Wall -Werror 编译器选项来证明未来,您可以对失败进行不同的编码(例如使用负值)并测试 foo < 0.0 - 直到有人发现浮点不等式可能也需要容忍度,并将构造声明为可疑。
使用浮点数时,有时会出现舍入问题。因此,通常不建议将计算结果与 == 或 != 进行比较,而是使用适当的界限,如 abs(a-b)<1.0e-10
.
但是用它来比较 0.0
合适吗?
这就是我所说的:
double foo(){
//code which can return values that aren't 0.0
//all returns are either literals or global variables defined with literals
return 0.0;
}
此处 f
将始终 return 恰好 0.0
或明确不是 0.0
的数字。具体来说,这些数字的大小都将大于 0.1
但小于 2.0
.
如果 return 是 0.0
,0.0==foo()
会一直是 true
吗?如果 foo
return 是 0.0
以外的值,0.0==foo()
是否有可能成为 true
?
最多 std::numeric_limits::digits<float>
你是安全的。这是因为尾数是整数类型(通常是特定于平台的 uint;然后通过符号位和指数扩展为浮点数)。
http://en.cppreference.com/w/cpp/types/numeric_limits/digits
如果你 return 一个文字 0.0
那么是的,但这通常不是一个好主意,因为虽然今天是这样,但你能确定在维护或代码重用下它会保持真实。最好编写一些可以在更广泛的环境中工作的代码。在这种情况下:
foo() < 0.1
对于您指定的所有值,将 return 为假。更通用的解决方案是测试是否足够接近零:
static const EPSILON = 0.00001 ;
std::fabs( foo() - 0.0 ) < EPSILON ;
最好使用上述模式之一,因为它不需要foo()
对"zero"的精度做出任何保证。
在你的情况下使用浮点相等是完全正确的== 0.0
。
它完全符合函数的意图(return 某个值,如果失败则为 0.0)。使用任何其他 epsilon 在某种程度上是任意的,并且需要了解正确值的范围。如果有什么事情发生变化,很可能是值的范围而不是 0,所以测试 == 0.0
与 IMO 的其他解决方案相比不亚于未来的证明。
我看到的唯一问题是一些编译器会警告相等性 (-Wfloat-equal) 的可疑使用...这与警告 int a,b,c; ...; c=a+b;
一样有用,因为这样的指令可能会导致问题 (整数溢出和未定义的行为)。奇怪的是,我从来没有看到第二个警告。
因此,如果您想使用 -Wall -Werror 编译器选项来证明未来,您可以对失败进行不同的编码(例如使用负值)并测试 foo < 0.0 - 直到有人发现浮点不等式可能也需要容忍度,并将构造声明为可疑。