将浮点数舍入到两位小数

时间:2016-09-08 21:47:01

标签: c floating-point rounding

我希望舍入一个浮点值,将val称为最接近的 0.05 的倍数。对我的意图的解释是here。我已经有val的上限和下限,分别说valUvalL。我可以通过以下方式做到这一点:

  1. [valL, valU]范围内搜索 0.05 的最接近倍数,并相应地指定值。通过降低价值来解决关系。 OR
  2. 使用this之类的内容(在链接中给出的解决方案中,偏离课程替换20乘以100)。
  3. 我发现方法-2有时会产生错误的结果。有人可以告诉我为什么方法-1是正确的方法吗?

1 个答案:

答案 0 :(得分:1)

  

...围绕float值,将val说成最接近0.05的倍数......

鉴于典型的binary floating point,最好的是

...将float值舍入到最接近0.05 R的倍数,并保存为最接近的可表示float r

方法#1在角落情况下不清楚。 OP所拥有的不是代码,而是从数学角度而非实际C代码的代码概要。我会选择#2非常的变体#2。 @Barmar

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

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

这种方法有两个微妙的点,使它更优越。

  1. 乘法的精确度和范围比引用的答案更高 - 这允许完全产品和非常精确商。如果仅使用float数学计算乘积/商,则某些边缘情况最终会得到错误答案,当然一些大值会溢出到无穷大。

  2. &#34;通过降低价值来解决问题。&#34;是一个艰难而不寻常的目标。听起来像是一个倾向于选择偏差的目标。无论当前的舍入方向如何,round(double)都可以很好地将半径从零开始。要完成&#34;降低&#34;,请更改当前的舍入方向并使用rint()nearbyint()

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

    ... method-2有时会产生错误的结果......

    OP需要发布代码和使用和计算的精确值,以便对各种方法的优缺点进行质量解释。试试printf("%a %a\n", val, rounded_val);。通常,由于对代码使用printf("%f\n", val);

    时使用的确切值的不精确理解而出现问题

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

    这是非常准确的,因为valUvalL的偏差只是原始问题的迭代 - 找到rounded_val。查找valLvalU的代码每个都需要一个上限和下限,否则什么是阻止范围[valL ... valU]本身具有不准确的端点?