伪浮点不等式由于编译器优化
Bogus float inequality due to compiler optimization?
我发现一些简单的代码在GCC 4.6.1与Visual Studio (2008 &2012)或Clang 7.3.0在OSX。
下面是一个简化的代码片段:
typedef float ftype;
struct Foo
{
ftype v;
Foo(): v(16.0f / 60.0f) {}
ftype val() const {return v * 60.0f;}
};
void bar()
{
Foo f;
ftype v = f.val();
if (v != f.val())
printf("inequal");
}
如果ftype被定义为double类型,那么问题就不会发生。这可能与编译器内联有关吗?也许实际上返回一个双精度而不是浮点数?
在代码片段中,您使用简单的"=="或"!="有效地比较了两个实数(浮点数或双精度数)是否相等。不幸的是,这种方法不能很好地处理实数,因为发生了浮点运算,也就是说,与整数相比,实数并没有准确地存储在内存中。
在比较两个实数时必须考虑一定的容差,这个容差取决于你使用的类型(float还是double)和机器。
虽然像下面这样的简单解决方案可能有效,但您必须将其集成到基于模板的代码中。
#include<limits>
#include<cmath>
TOL=std::numeric_limits<float>::epsilon()
if (std::abs(v - f.val())<TOL)
{
//some code
}
,你应该看一下浮点指南。这些在StackOverflow上的答案也应该有所帮助:
如何正确、标准地比较浮点数?
浮点和双精度比较最有效的方法是什么?
UPD: bug只使用差值而不是根据@doug的注释更正的abs值
相关文章:
- 如何解决gcc编译器优化导致的centos双编译器设置中的分段错误
- 使用仅使用一次的变量调用的复制构造函数.这可能是通过调用move构造函数进行编译器优化的情况吗
- 这个C++编译器优化(在自身的实例上调用对象自己的构造函数)的名称是什么,它是如何工作的?
- VS2017调试器:没有地址,可能是由于编译器优化
- 何时允许编译器优化复制构造函数
- 如何使用 GCC 编译器优化创建静态库?
- 为什么 std::chrono 在测量循环和编译器优化的并行 OpenMP 的执行时间时不起作用?
- 是否允许编译器优化掉局部易失性变量
- 删除编译器优化并在发布中启用 pdb 文件
- 静态 constexpr 的编译器优化
- 如何让MSVC编译器优化多步POD初始化?
- 按位不操作的编译器优化
- 模板专用化与编译器优化
- 编译器优化:G 比英特尔慢
- 运算符重载关联性编译器优化
- Intel OpenCL编译器:优化结构使用情况
- C 中编译器优化的影响
- 视觉C++ 2017 错误?编译器优化表达式
- 虚拟功能编译器优化C
- 未定义的行为确实有助于现代编译器优化生成的代码