为什么2.9000000000000004而不是2.9?

这个问题在这里已经有了答案:

  • 浮点数学是否被破坏? 23个答案

  • 我如何告诉ghci不要这样做,并像其他编程语言(和计算器)一样,每两年15岁就会显示双倍操作的结果?

    由于这些结果是GHCI(和标准计算器*)计算的实际结果,因此您无法更改结果的内部表示形式(请参阅TNI的答案)。 既然你只想显示一个固定的小数位数,那么它更像是一个演示文稿(与printf("%f.2",...) )。

    这个解决方案可以在https://stackoverflow.com/a/2327801/1139697找到。 它可以像这样应用:

    import Numeric
    fixedN :: (RealFloat b) => Int -> b -> String
    fixedN a b = showFFloat (Just a) b ""
    
    map (fixedN 2 . (-)2.3) [4.0, 3.8, 5.2, 6.4, 1.3, 8.3, 13.7, 9.0, 7.5, 2.4]
    -- result: ["-1.70","-1.50","-2.90","-4.10","1.00","-6.00",...]
    

    请注意,如果您想继续计算,这将不可行。 如果你想要精确的算术,你最好还是使用Rationals 。 不要忘记,在这种情况下,你的投入应该是理性的。

    *是的,即使你的标准计算器也做同样的事情,你没有看到它的唯一原因是固定的演示文稿,它不能显示超过固定的小数位数。


    为什么会发生?

    因为某些浮点数不能用没有舍入的有限位数表示。 浮点数字的位数是有限的,它们不能准确地表示所有的实数:当位数多于格式允许的数字时,剩余的数字被省略 - 数字被舍入。

    你应该阅读每个计算机科学家应该知道的关于浮点算术和这个答案。


    这是浮点数的本质,它们不能准确表示真实(或合理)的数字。 Haskell默认转换为字符串可确保在读取数字时获得完全相同的表示形式。 如果你想以不同的方式打印数字,你可以使自己的类型显示不同的数字。

    像(未经测试)的东西:

    newtype MyDouble = MyDouble {getMyDouble :: Double}
                deriving (Eq, Ord, Num, Real, RealFrac, Fractional, Floating)
    instance Show MyDouble where show = printf "%g" . getMyDouble
    default (MyDouble)
    

    这将创建一个Double类型的副本,但使用不同的Show实例,只打印几位小数。 default声明使得编译器在存在歧义时选择此类型。 哦,为了使这项工作,你需要一些语言扩展。

    您也可以尝试numbers包中的CReal类型。

    链接地址: http://www.djcxy.com/p/27455.html

    上一篇: why 2.9000000000000004 instead of 2.9?

    下一篇: point behaviour in a Java program