7

我想用偏差来舍入浮点数,要么总是向下,要么总是向上。代码中有一个特定点我需要这个,程序的其余部分应该像往常一样四舍五入到最接近的值。

例如,我想四舍五入到最接近的 1/10 倍数。最接近 7/10 的浮点数约为 0.69999998807,但最接近 8/10 的浮点数约为 0.80000001192。当我对数字进行四舍五入时,这是我得到的两个结果。我宁愿让它们以同样的方式四舍五入。7/10 应四舍五入为 0.70000004768,8/10 应四舍五入为 0.80000001192。

在这个例子中,我总是向上取整,但我有一些地方我想总是向下取整。幸运的是,我只在这些地方处理积极的价值观。

我用来四舍五入的线是floor(val * 100 + 0.5) / 100. 我正在用 C++ 编程。

4

1 回答 1

11

我认为实现这一点的最佳方法是依靠以下事实:根据 IEEE 754 浮点标准,浮点位的整数表示按字典顺序排列为 2 补码整数。

即你可以简单地添加一个ulp(最后一个单位)来获得下一个浮点表示(如果它更小,它总是会比你的阈值略大,因为圆形误差最多为1/2 ulp)

例如

 float floatValue = 7.f/10;
 std::cout << std::setprecision(20) << floatValue << std::endl;
 int asInt = *(int*)&floatValue;
 asInt += 1;
 floatValue = *(float*)&asInt;
 std::cout << floatValue << std::endl;

打印(在我的系统上)

 0.69999998807907104492
 0.70000004768371582031

floor要知道何时需要添加一个ulp ,您必须依赖floor

 if (std::floor(floatValue * 100.) != std::floor(floatValue * 100. + 0.5)) {
    int asInt = *(int*)&floatValue;
    asInt += 1;
    floatValue = *(float*)&asInt;
 }

将正确地将 0.69.. 转换为 0.70.. 但不理会 0.80..。

100.请注意,在应用之前,浮点数通过与乘法提升为双精度floor

如果你不这样做,你就有可能陷入这样的境地

 7.f/10.f * 100.f

(精度有限)浮点表示将是 70.00...

于 2009-03-26T15:28:04.830 回答