我希望将浮点值取整,例如val到其最接近的0.05倍数。我的意图的解释是here。我已经有了val的上限和下限,分别说valUvalL。我可以通过以下方式做到这一点:


[valL, valU]范围内搜索0.05的最接近倍数,并相应地分配值。领带的价值较低。要么
使用类似this的方法(在链接中给出的解决方案中,用20代替100)。


我发现方法2有时会产生错误的结果。有人可以告诉我为什么方法1是正确的方法吗?

最佳答案

...将float值四舍五入,例如val到最接近的0.05倍...


给定典型的binary floating point,最好的选择是

...将float值四舍五入到最接近0.05 R的倍数,然后另存为最接近的可表示的float r



在极端情况下,方法#1尚不清楚。 OP没有的不是代码,而是从数学角度讲的代码概述,而不是实际的C代码。我会在#2上做一个很好的变体。 @Barmar

几乎方法2:相乘,四舍五入然后相除。

#include <math.h>
double factor = 20.0;
float val = foo();
double_or_float rounded_val = round(val * factor)/factor;


此方法有两个微妙之处,使其具有优越性。


乘法比参考答案具有更高的精度和范围-这允许精确的乘积和非常精确的商。如果乘积/商仅使用float数学计算,则某些边缘情况最终将给出错误的答案,当然,某些较大的值将溢出至无穷大。
“关系是通过降低价值来解决的。”是一个艰巨而不同寻常的目标。听起来像是针对偏斜选择的目标。 round(double)很好地舍入了零的中途情况,而不管当前的舍入方向如何。若要完成“降低”,请更改当前舍入方向,并使用rint()nearbyint()

#include <fenv.h>
int current_rounding_direction = fegetround();
fesetround(FE_DOWNWARD);
double rounded_val = rint(val * factor)/factor;
fesetround(current_rounding_direction);






  ...方法2有时会产生错误的结果...


OP需要发布代码以及使用和计算的确切值,以对各种方法的优势/劣势进行质量说明。尝试printf("%a %a\n", val, rounded_val);。通常,由于对代码使用printf("%f\n", val);时所使用的确切值的不正确理解而导致出现问题



此外:“我已经有了val的上限和下限,分别说valUvalL。我可以通过以下方式做到这一点:”

这无疑是准确的,因为valUvalL的偏差只是原始问题的迭代-查找rounded_val。查找valLvalU的代码分别需要一个上限和下限,否则如何防止范围[valL ... valU]本身具有不正确的端点?

10-05 18:19