【问题标题】:Why different results of 0.5 mod 0.1 in different programming languages?为什么在不同的编程语言中 0.5 mod 0.1 的结果不同?
【发布时间】:2011-04-11 07:40:16
【问题描述】:

我有一个关于模数的问题。模运算求一个数除以另一个数的余数。我期待 0.5 % 0.1 = 0 的结果。但是当我在 PHP 或 .net 中运行它时,我得到 0.1。

我运行的php中的代码是:

var_dump(fmod(0.5, 0.1));

在 .net 中,我尝试了以下结果:

Console.WriteLine(0.5%0.1);

我还尝试了一个在线计算器http://www.calculatorpro.com/modulo-calculator/

所有这 3 种方法都给了我 0.1 作为答案。

但是当我在谷歌中输入这个时,我得到了我期望的结果http://www.google.nl/search?source=ig&hl=nl&q=0.5%20mod%200.1&meta=

这是 .net/php 中的错误还是谷歌知道正确的答案?谁能解释为什么会出现这些差异?

【问题讨论】:

标签: php .net modulo


【解决方案1】:

当您要求 0.1 时,您在 PHP、C#、C++ 或 Python 中得到的数字是双精度浮点数,这意味着它是一个有限的“十进制”——有 53 个有效位,包括第一个 1 -bit -- 以 2 为基数。事实上,你会得到最接近 0.1 的可精确表示的数字,我认为它正好是 0.1000000000000000055511151231257827021181583404541015625。

另一方面,0.5 有限的“双数”;当您要求时,您得到的值将正好是 0.5。

因此,0.5 只是略小于“0.1”的 5 倍,因此“0.5 mod 0.1”实际上给您的结果略小于 0.1。其实我觉得正好是0.09999999999999997779553950749686919152736663818359375。

现在,当您要求 PHP 或 C# 或任何其他工具显示此数字时,它会显示一些有限的数字。你真的不希望它显示整个可怕的事情。 (考虑一下:假设您只要求显示 0.1;您想要一个无数位数的怪物,还是想要“0.1”?这么想。)这个数字实际上非常接近 0.1;除非您要求超过 15 位的精度,否则正确显示的内容仅为“0.1”。

观察(这是 Python,我碰巧有它):

>>> for n in range(10,20): print (("%%.%dg"%n)%(0.5%0.1))

0.1
0.1
0.1
0.1
0.1
0.1
0.09999999999999998
0.099999999999999978
0.0999999999999999778
0.0999999999999999778

所以:不是错误;并不是浮点不适合“精确计算”的问题(有时它是合适的,有时不是;问题是要了解它在做什么以及你需要什么);可能会或可能不会表明您会更好地使用整数,这取决于您的实际需求。

如果您想了解更多关于这些内容的信息,请查看"What every computer scientist should know about floating-point arithmetic"

至于为什么 Google 的计算器给出的预期答案是 0,我不知道。也许他们正在使用十进制算术 - 真正的以 10 为底的数字 - 以尽量减少意外的惊喜。 (这通常比使用原生浮点要慢得多,但 Google 有很多可用的 CPU,我敢打赌,他们的搜索处理机器所做的工作中只有一小部分与计算器。)

【讨论】:

    【解决方案2】:

    不,这不是错误,因为模运算也可以在浮点数上定义。在您的 PHP 代码中,您明确使用 fmod() 而不是 %,而在 .NET 中,% 运算符是在每个数字类型上定义的 (check reference)

    【讨论】:

      【解决方案3】:

      0 是整数答案,0.1 是正确的浮点结果

      另外看看 wolframalpha:http://www.wolframalpha.com/input/?i=0.5+mod+0.1

      【讨论】:

      • “0 是整数答案”,你的意思是“0 是有理答案”。
      【解决方案4】:

      如果您想评估0.5%0.1,您可能(并且应该)使用整数运算。例如,如果您正在计算涉及货币的东西,通常将美分数存储为整数比将金额存储为浮点数更好。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-06-30
        • 2016-12-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-12-23
        • 1970-01-01
        • 2011-02-07
        相关资源
        最近更新 更多