我偶然发现了一个失败的单元测试,其中涉及将双精度数转换为整数。
实际转换的数字是
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);
}