在 x86 和 x86_64 上将浮点数截断为 int 具有不同的舍入误差

问题描述 投票:0回答:1

我偶然发现了一个失败的单元测试,其中涉及将双精度数转换为整数。

实际转换的数字是

1.234 * 1000.
,代码基本上可以归结为:

#include <stdio.h>
#include <stdint.h>

int64_t deltatime(double numSeconds) {
        return (int64_t) (numSeconds * 1000.0);
}

int main() {
        double s = 1.234;
        int64_t ms = deltatime(s);
        printf("%fs -> %dms\n", s, ms);
        return 0;
}

现在为 x86-64 编译这个,给我:

$ gcc test.c && ./test
1.234000s -> 1234ms

针对 x86-32 编译它,给我:

$ gcc -m32 test.c && ./test
1.234000s -> 1233ms

(这是与

$ gcc --version
gcc (Debian 14.2.0-7) 14.2.0

现在,我明白数字

1.234
无法在IEEE-754中精确表示, 例如在单精度浮点数中,它确实是
1.2339999675750732421875
,同样,在双精度浮点数中,它是
1.2339999999999999857891452848

现在,将实际值乘以

1000.0
(可以精确表示),应该总是给我
1233.9999...
,并将其转换为
int64_t
实际上会是
1233
(而不是天真的预期的
1234
) .

但是为什么我在 x86-64 上得到

1234
(没有为编译器指定任何舍入选项)?

正确的解决方案是否只是将

0.5
添加到总和中(before 转换为
int64_t
)?

int64_t deltatime(double numSeconds) {
        return (int64_t) (numSeconds * 1000.0 + 0.5);
}
c gcc x86 x86-64 rounding-error
1个回答
-1
投票

自 C++11 起,您可以

#include <cmath>
并使用 std::llround()

© www.soinside.com 2019 - 2024. All rights reserved.