不,您需要比较(long double)x == (long double)y
长双精度尾数可以容纳 63 位的架构。这是因为当您将一些大的 long long int 转换为浮点数时,它们会失去精度,并与非等效浮点数进行比较,但如果您转换为 long double,它不会在该架构上失去精度。
下面的程序演示了gcc -std=c99 -mssse3 -mfpmath=sse
在 x86 上编译时的这种行为,因为这些设置使用了足够宽的长双精度,但防止在计算中隐式使用更高精度的类型:
#include <assert.h>
#include <stdint.h>
const int64_t x = (1ULL<<62) - 1ULL;
const float y = (float)(1ULL<<62);
// The mantissa is not wide enough to store
// 63 bits of precision.
int main(void)
{
assert ((float)x == (float)y);
assert ((long double)x != (long double)y);
return 0;
}
编辑:如果你没有足够宽的长双打,以下可能会起作用:
feclearexcept(FE_ALL_EXCEPT);
x == y;
ftestexcept(FE_INEXACT);
我认为,尽管我可能弄错了,但实现可能会在转换过程中以失去精度的方式舍入 x。
另一个可行的策略是比较
extern uint64_t x;
extern float y;
const float z = (float)x;
y == z && (uint64_t)z == x;
这应该会捕获由于舍入误差导致的精度损失,但如果转换为 z 舍入,它可能会导致未定义的行为。如果在将 x 转换为 z 时将转换设置为向零舍入,它将起作用。