【问题标题】:Interesting modulo operation result有趣的模运算结果
【发布时间】:2013-06-11 08:03:14
【问题描述】:

在我的 Windows 桌面上,我将两个数字相乘:

var a:Number = 31.05263157894737;
trace(a * 19) // will print '590'

很明显,590 除以a 余数为 0,对吧?好吧,由于某种原因,我得到了不同的结果:

trace(590 % a) // will print '31.05263'

我的问题是 这是怎么发生的?为什么 1 % 0.5 给出正确的余数 0?

【问题讨论】:

    标签: math actionscript floating-point precision modulo


    【解决方案1】:

    31.05263157894737 * 19 不完全是590,它是590.00000000000003

    换句话说,590.00000000000003 % 31.05263157894737 = 0,但由于590 略小,它只比达到/环绕到 0 所需的略小。

    无论哪种方式,即使您使用了源代码中看起来像精确的数字,也很少会在浮点数学中为您提供精确的结果,因为并非所有数字都可以用单/双类型精确表示,即使是微小的舍入误差也可以(在这种情况下)给出相当不明显的结果。

    【讨论】:

    • 动作脚本内部是否使用十进制浮点数?否则我们可以添加 31.05263157894737(双精度)可能不是 31.05263157894737(小数部分)
    • "31.05263157894737 * 19 不完全是 590" 嗯,它是在计算为 IEEE-754 双精度数时。看起来它是使用扩展精度计算的 - 或者文字被错误地转换为 31.052631578947373469645754084922373294830322265625 而不是 31.052631578947369916932075284421443939208984375。 (可能是 Action Script 在这里偏离了 ECMA Script 并允许这种情况发生,ECMA 要求转换为最接近的值。)
    • @DanielFischer 不是 % 运算符后面的 libm fmod 吗?如果是这种情况,并且 fmod 被正确实现,它就像执行精确的商和余数一样,然后将结果四舍五入到最接近的浮点值。
    猜你喜欢
    • 2015-03-19
    • 1970-01-01
    • 1970-01-01
    • 2016-12-11
    • 2016-11-26
    • 1970-01-01
    • 2018-08-22
    • 2015-02-16
    相关资源
    最近更新 更多