在我的数值模拟中,我的代码类似于以下代码段
double x; do { x = /* some computation */; } while (x <= 0.0); /* some algorithm that requires x to be (precisely) larger than 0 */
对于某些平台上的某些编译器(例如gcc)(例如linux,x87 math),有可能x
以高于双精度("具有过度精度")的方式计算.(更新:当我在这里谈到精度时,我的意思是精度/和/范围.)在这种情况下,可以想象,x <= 0
即使下一次x向下舍入到双精度,它也会变为0,而compare()返回false.(和无法保证x不会在任意时间点向下舍入.)
有没有办法进行这种比较
便携,
适用于内联的代码,
没有性能影响
不排除某些任意范围(0,eps)?
我尝试使用(x < std::numeric_limits
)但是在使用SSE2数学时,这似乎显着减慢了循环.(我知道非正规可以减慢计算速度,但我没想到它们只是移动并比较慢.)
更新:
另一种方法是在比较之前使用volatile
强制x
进入内存,例如通过写入
} while (*((volatile double*)&x) <= 0.0);
但是,根据应用程序和编译器应用的优化,此解决方案也会引入明显的开销.
更新: 任何容忍的问题是它是非常随意的,即它取决于具体的应用程序或上下文.我更愿意在没有过多精度的情况下进行比较,这样我就不必做任何额外的假设或在我的库函数的文档中引入一些任意的epsilons.
正如Arkadiy在评论中指出的那样,一个明确的演员((double)x) <= 0.0
应该有效 - 至少根据标准.
C99:TC3,5.2.4.2.2§8:
除了赋值和强制转换(删除所有额外的范围和精度)之外,具有浮动操作数的操作值和受常规算术转换和浮动常量限制的值将被评估为其范围和精度可能大于类型.[...]
如果在x86上使用GCC,则可以使用标志-mpc32
,-mpc64
并将-mpc80
浮点运算的精度设置为单精度,双精度和双精度.