【发布时间】:2019-08-05 22:04:27
【问题描述】:
我正在研究浮点确定性,并且已经研究了许多令人惊讶的不确定性潜在原因,我开始对复制浮点数感到偏执:
C++ 标准中的任何内容或一般情况下是否向我保证浮点左值在复制到另一个浮点变量或用作 const-ref 或按值参数时,将始终按位等效于原始值?
任何事情都会导致复制的浮点数按位与原始值等效,例如更改浮点环境或将其传递到不同的线程?
以下是一些示例代码,基于我在测试用例中检查浮点值等价性所使用的代码,这会失败,因为它需要 FE_TONEAREST:
#include <cfenv>
#include <cstdint>
// MSVC-specific pragmas for floating point control
#pragma float_control(precise, on)
#pragma float_control(except, on)
#pragma fenv_access(on)
#pragma fp_contract(off)
// May make a copy of the floats
bool compareFloats(float resultValue, float comparisonValue)
{
// I was originally doing a bit-wise comparison here but I was made
// aware in the comments that this might not actually be what I want
// so I only check against the equality of the values here now
// (NaN values etc. have to be handled extra)
bool areEqual = (resultValue == comparisonValue);
// Additional outputs if not equal
// ...
return areEqual;
}
int main()
{
std::fesetround(FE_TOWARDZERO)
float value = 1.f / 10;
float expectedResult = 0x1.99999ap-4;
compareFloats(value, expectedResult);
}
我是否必须担心,如果我将浮点值传递给比较函数,即使它是左值,它在另一端的结果可能会有所不同?
【问题讨论】:
-
您对 NaN 在位稳定性方面的行为感兴趣吗?
-
另外,如果您还没有阅读randomascii.wordpress.com/2013/07/16/floating-point-determinism,我建议您阅读。
-
randomascii 上的浮点系列和 gafferongames 文章是我的主要来源,还有一些散布在博客中的信息。关于 NaN:如果 NaN 是通过相同的机制产生的,我的按位检查应该适用于那些,不是吗?
-
需要明确的是,这不是由 C++ 标准控制的,而是由您的编译器/平台、它对 IEEE-754 的遵守以及可用选项的确切影响。使用
/fp:fast而不是/fp:precise进行编译不会使编译器违反 C++ 标准,因为指示浮点处理超出了 C++ 的范围。 -
@Ident:您对确定性的担忧似乎是确保浮点算术得到正确的结果,或者至少在规范内得到正确的结果,或者至少在通过不同方式计算时得到相同的结果。为此,您应该只关心表示的值,而不是表示它们的位,除了 NaN 中的任何有效负载数据。在某些浮点算术系统中,一个值以多种方式表示是完全正常的,例如 9•10^-1 和 90•10^-2 用于 .9。
标签: c++ floating-point precision floating-accuracy