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

iphone与浮点数学

  •  1
  • leon  · 技术社区  · 15 年前

    我有以下代码:

        float totalSpent;
        int intBudget;
        float moneyLeft;
    
    totalSpent += Amount;
    moneyLeft =  intBudget - totalSpent;
    

    这就是它在调试器中的外观: http://www.braginski.com/math.tiff

    为什么由上面的代码计算的moneyleft与由调试器计算的表达式相差0.02?

    表达式窗口是正确的,但是上面的代码产生了错误的by.02结果。它只发生在非常大的数字上(但远低于整数限制)

    谢谢

    2 回复  |  直到 15 年前
        1
  •  4
  •   Crashworks    15 年前

    单精度 float 有23位精度。这意味着每次计算都会四舍五入到23位二进制数字。这意味着,如果你有一个计算,比如说,把一个非常小的数加到一个非常大的数上,舍入可能会导致奇怪的结果。

    假设你是用科学记数法手工计算十进制数,根据规则,你可能只有四个有效数字。假设我让你用科学记数法写十二个,四个有效数字。回忆起初中,你写道:

    1.200×10

    现在我要计算12的平方,然后加0.5。这很简单:

    1.440×10 + 0.005×10 =1.445×10

    十二立方加上0.75怎么样:

    1.728×10 +0.00075×10 =1.72875×10

    但请记住,我只给你空间 四位有效数字 ,所以你必须 ;然后我们得到:

    1.728×10 + 7.5×10 - 1 =1.729×10

    看到了吗?精度的不足会使计算结果出人意料。

    在你的例子中,你在一个计算中得到了999999,你试图精确到0.01。日志 (999999)=19.93和对数 (0.01)=-6.64。差异大于23;因此,要准确执行此计算,需要超过23个二进制数字。

    因为浮点数学本质上是精确的,所以它通常是货币计算的一个错误选择,在货币计算中必须精确到最后一分。但你真的关心你申请表中的零头吗?如果不是,那为什么不干脆去掉小数点,把美分(而不是美元)存储在64位整数中呢?二 六十四 ,超过了整个地球的GDP。

        2
  •  3
  •   James Anderson    15 年前

    浮点运算总是会产生奇怪的货币类型计算结果。

    黄金法则是,浮点数对你测量升、码、光年、蒲式耳等的事物是好的,但对你计算的事物不是好的 羊、豆子、纽扣等。

    大多数的金钱计算都是为了数硬币,所以使用整数数学 你不会得到奇怪的结果。要么使用固定的十进制算术 图书馆(在iphone上可能会被过度使用)或者存储你的数量 整个数字的美分和只转换成美元和美分的展示。