代码之家  ›  专栏  ›  技术社区  ›  izb

为什么我的数字四舍五入错误?

  •  7
  • izb  · 技术社区  · 15 年前

    这感觉像是一种只在原地失败的代码,但我会尝试将它调整为一个代码片段,以表示我所看到的内容。

    float f = myFloat * myConstInt; /* Where myFloat==13.45, and myConstInt==20 */
    int i = (int)f;
    int i2 = (int)(myFloat * myConstInt);
    

    单步执行代码后,i==269,i2==268。这里发生了什么事来解释这个差异?

    5 回复  |  直到 15 年前
        1
  •  15
  •   Community CDub    8 年前

    浮点数可以以比广告更高的精度执行。但一旦你把它存储在float f中,额外的精度就会丢失。当然,在第二个方法中,直到您将结果强制转换为int之后,您才会失去该精度。

    编辑:查看此问题 Why differs floating-point precision in C# when separated by parantheses and when separated by statements? 比我可能提供的更好的解释。

        2
  •  4
  •   technophile    15 年前

    因为浮点变量不是 infinitely accurate . 如果你需要这种精确性,就用十进制。

    不同 rounding modes 可能也会涉及到这个问题,但准确度问题是你在这里遇到的,阿法克。

        3
  •  2
  •   Steve314    15 年前

    浮点数的精度有限,它基于二进制而不是十进制。十进制数字13.45不能精确地用二进制浮点表示,因此向下舍入。乘以20进一步夸大了精度的损失。现在你有268.999…-不是269-因此,到整数的转换将截断为268。

    要将四舍五入到最接近的整数,可以尝试在转换回整数之前添加0.5。

    对于“完美”算术,您可以尝试使用十进制或有理数字类型-我相信C有两种类型的库,但不确定。然而,这些速度会变慢。

    编辑 -到目前为止,我已经找到了一个“十进制”类型,但不是一个理性的类型——我可能错了。小数浮点数是不准确的,就像二进制一样,但它是我们习惯的那种不准确,所以它给出的结果不那么令人惊讶。

        4
  •  1
  •   Martin    15 年前

    替换为

    double f = myFloat * myConstInt;
    

    看看你是否得到同样的答案。

        5
  •  1
  •   Rick Regan    15 年前

    我想给出一个不同的解释。

    这是我注释过的代码(我查看内存以剖析浮动):

     float myFloat = 13.45; //In binary is 1101.01110011001100110011
     int myConstInt = 20;
     float f = myFloat * myConstInt; //In binary is exactly 100001101 (269 decimal)
     int i = (int)f; // Turns float 269 into int 269 -- no surprises
     int i2 = (int)(myFloat * myConstInt);//"Extra precision" causes round to 268
    

    让我们仔细看看计算:

    • F=1101.0110011001100110011*10101=100001100.111111111111111 111

      空格后的部分是位25-27,这导致位24向上取整,因此整数值向上取整为269。

    • int i2=(int)(myfloat*myconstint)

      MyFloat扩展到双精度计算(追加0s):1101.011001100110011000000000000000000000000000000

      myfloat*20=100001100.11111111111111111100000000000000000000000万

      位54及以上为0,因此不进行取整:转换结果为整数268。

      (如果使用扩展精度,类似的解释也会起作用。)

    更新:我完善了我的答案,写了一篇全面的文章,叫做 When Floats Don’t Behave Like Floats