我希望将浮点值取整,例如val
到其最接近的0.05倍数。我的意图的解释是here。我已经有了val
的上限和下限,分别说valU
和valL
。我可以通过以下方式做到这一点:
在[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
的上限和下限,分别说valU
和valL
。我可以通过以下方式做到这一点:”这无疑是准确的,因为
valU
和valL
的偏差只是原始问题的迭代-查找rounded_val
。查找valL
和valU
的代码分别需要一个上限和下限,否则如何防止范围[valL ... valU]
本身具有不正确的端点?