【问题标题】:Reliable cube root in HaskellHaskell 中可靠的立方根
【发布时间】:2010-12-22 10:10:36
【问题描述】:

我在项目 euler 做question 62 并想出了以下测试数字是否为三次:

isInt x = x == fromInteger (round x)
isCube x= isInt $ x**(1/3)

但由于浮点错误,返回不正确的结果:

*Main> isCube (384^3)
False

有没有办法实现更可靠的立方体测试?

顺便说一句,这是我的解决方案的其余部分,由于filter (isCube) (perms n) 上的类型接口错误,它不起作用:

cubes = [n^3|n<-[1..]]
perms n = map read $ permutations $ show n :: [Integer]
answer = head [n|n<-cubes,(length $ filter (isCube) (perms n)) == 5]

我需要做什么来修复错误?

No instances for (Floating Integer, RealFrac Integer)
   arising from a use of `isCube' at prob62.hs:10:44-49

也欢迎任何优化;-)

【问题讨论】:

    标签: haskell root


    【解决方案1】:

    有关对Integer 值有用的另一种方法,请查看arithmoi package 中的integerCubeRoot 函数。

    例子:

    ghci> import Math.NumberTheory.Powers.Cube
    ghci> let x = 12345^3333
    ghci> length $ show x
    13637
    ghci> isCube x
    True
    ghci> isCube (x+1)
    False
    ghci> length $ show $ integerCubeRoot x
    4546
    

    【讨论】:

      【解决方案2】:

      尽量避免使用浮点数,尤其是当您遇到与整数值有关的问题时。浮点数存在舍入问题,某些值(如 1/3)无法准确表示。所以你得到神秘的答案也就不足为奇了。

      首先,为了修复你的类型错误,你必须重新定义isCube。如果你检查它的类型签名,它看起来像这样:

      isCube :: (RealFrac a, Floating a) => a -> Bool
      

      请注意,它需要 Floating 类的东西作为它的第一个参数。您的问题是您想对整数值使用此函数,而整数不是Floating 的实例。你可以像这样重新定义isCube来进行函数类型检查。

      isCube x = isInt $ (fromIntegral x) ** (1/3)
      

      但是,这不会使您的程序正确。

      使您的程序更正确的一种方法是按照 Henrik 的建议进行操作。它看起来像这样:

      isCube x = (round (fromIntegral x ** (1/3))) ^ 3 == x
      

      祝你好运!

      【讨论】:

        【解决方案3】:

        perms 的类型为 [Integer]isCube 的类型为 (RealFrac a, Floating a) =&gt; a -&gt; Bool(您可以在 GHCI 中查看)。 RealFrac 约束来自round xFloating 约束来自x**(1/3)。由于Integer 既不是RealFrac 也不是FloatingisCube 不能 用作Integer -&gt; Bool。所以filter isCube (perms n) 没有意义。

        所以你需要修复isCube 才能在Integers 上正常工作:

        isCube x = isInt $ (fromInteger x)**(1/3)
        

        事实上,isCube (384^3) 甚至编译的原因是它“真的”意味着isCube ((fromInteger 384)^(fromInteger 3))

        当然,由于浮点错误,这仍然无法正常工作。基本上,检查浮点数是否相等,就像您在isInt 中所做的那样,几乎总是一个坏主意。请参阅其他答案以了解如何进行更好的测试。

        【讨论】:

          【解决方案4】:

          对 Haskell 了解不多,但我会取立方根,四舍五入到最接近的整数,取立方,然后与原始值进行比较。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-11-26
            • 1970-01-01
            • 2011-05-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多