我想问一个关于以下方程式的问题:
value = (floor(((value - min) + (step / 2)) / step) * step) + min;
Run Code Online (Sandbox Code Playgroud)
我使用它来将输入值限制为给定无符号整数类型的最小值的步长。
我已经使用了一段时间,并且效果很好,直到最近发现它可以产生意想不到的效果。以下程序演示了我的观点:
// test.cpp
#include <cstdio>
#include <cstdlib>
#include <cstdint>
#include <cinttypes>
#include <cmath>
int main(void)
{
uint64_t value = 2305913515935801433;
uint64_t min = value;
uint64_t step = 1;
uint64_t result1 = (value - min) + (step / 2);
uint64_t result2 = ((value - min) + (step / 2)) / step;
uint64_t result3 = floor(((value - min) + (step / 2)) / step);
uint64_t result4 = (floor(((value - min) + (step / 2)) / step) * step);
uint64_t result5 = (floor(((value - min) + (step / 2)) / step) * step) + min;
uint64_t result6_ = (floor(((value - min) + (step / 2)) / step) * step);
uint64_t result6 = result6_ + min;
printf("result1 = %" PRIu64 " (0x%" PRIX64 ")\n", result1, result1);
printf("result2 = %" PRIu64 " (0x%" PRIX64 ")\n", result2, result2);
printf("result3 = %" PRIu64 " (0x%" PRIX64 ")\n", result3, result3);
printf("result4 = %" PRIu64 " (0x%" PRIX64 ")\n", result4, result4);
printf("result5 = %" PRIu64 " (0x%" PRIX64 ")\n", result5, result5);
printf("result6 = %" PRIu64 " (0x%" PRIX64 ")\n", result6, result6);
return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)
使用以下命令在64位Linux上编译:
g++ -Wall --std=c++11 -o test test.cpp
Run Code Online (Sandbox Code Playgroud)
结果:
result1 = 0 (0x0)
result2 = 0 (0x0)
result3 = 0 (0x0)
result4 = 0 (0x0)
result5 = 2305913515935801344 (0x2000402020202000)
result6 = 2305913515935801433 (0x2000402020202059)
Run Code Online (Sandbox Code Playgroud)
如您所见,具有完整方程式(result5)的结果是错误的,并且以某种方式清除了最后一个字节。最后的两部分结果(结果6)是正确的。
我无法解释第五个结果失败的原因。我在这里想念什么?
提前致谢!
| 归档时间: |
|
| 查看次数: |
134 次 |
| 最近记录: |