首页 > 解决方案 > 是否保证浮点变量的副本将按位等同于原始变量?

问题描述

我正在研究浮点确定性,并且已经研究了许多令人惊讶的不确定性的潜在原因,我开始对复制浮点数感到偏执:

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);
}

我是否必须担心,如果我将浮点值传递给比较函数,即使它是左值,它在另一边的结果可能会有所不同?

标签: c++floating-pointprecisionfloating-accuracy

解决方案


不,没有这样的保证。

次规范、非规范化浮点和 NaN 都是位模式可能不同的情况。

我相信带符号的负零可以在分配时变成带符号的正零,尽管 IEEE754 不允许这样做。


推荐阅读