确定Int是否是Haskell中的完美正方形的方法是什么?

Val*_*lev 13 algorithm haskell sqrt

我需要一个简单的功能

is_square :: Int -> Bool
Run Code Online (Sandbox Code Playgroud)

它确定Int N是否是一个完美的正方形(是否存在整数x,使得x*x = N).

当然我可以写一些类似的东西

is_square n = sq * sq == n
    where sq = floor $ sqrt $ (fromIntegral n::Double)
Run Code Online (Sandbox Code Playgroud)

但它看起来很糟糕!也许有一种常见的简单方法来实现这样的谓词?

Jul*_*iet 10

想想这样说,如果你有一个积极的INT n,那么你基本上做的数字从1范围内的二进制搜索... N找到的第一个数字n'在那里n' * n' = n.

我不知道Haskell,但这个F#应该很容易转换:

let is_perfect_square n =
    let rec binary_search low high =
        let mid = (high + low) / 2
        let midSquare = mid * mid

        if low > high then false
        elif n = midSquare then true
        else if n < midSquare then binary_search low (mid - 1)
        else binary_search (mid + 1) high

    binary_search 1 n
Run Code Online (Sandbox Code Playgroud)

保证为O(log n).易于修改完美的立方体和更高的功率.

  • 我非常喜欢这个解决方案.我一直对二进制搜索对于不同事物的有用程度感到惊讶.但是,O(log n)具有误导性.您将预先形成O(log n)次迭代,但是在每次迭代中,您都有一个隐藏的mid*mid.平方数大约需要O(mlogm).m接近sqrt(n),所以假设m = sqrt(n).对于m = sqrt(n),其最终效率实际上是O(log n)*O(m log m).仍为,二进制搜索+1:P (4认同)

rec*_*nja 10

对于Haskell中包含的大多数数论相关问题,有一个很棒的arithmoi.

使用该Math.NumberTheory.Powers.Squares库.

特别是isSquare'功能.

is_square :: Int -> Bool
is_square = isSquare' . fromIntegral
Run Code Online (Sandbox Code Playgroud)

图书馆经过优化,并且受到人们更加专注于提高效率的人们的审查.虽然目前还没有这种恶作剧,但随着图书馆的发展和更加优化,它可能会在未来发生.查看源代码以了解其工作原理!

不要重新发明轮子,总是在可用时使用库.


ear*_*ess 6

我认为您提供的代码是您获得的最快的代码:

is_square n = sq * sq == n
    where sq = floor $ sqrt $ (fromIntegral n::Double)
Run Code Online (Sandbox Code Playgroud)

这段代码的复杂性是:一个sqrt,一个double乘法,一个cast(dbl-> int)和一个比较.您可以尝试使用其他计算方法将sqrt和乘法替换为仅整数算术和移位,但可能不会比一个sqrt和一个乘法更快.

唯一值得使用其他方法的地方是运行的CPU不支持浮点运算.在这种情况下,编译器可能必须在软件中生成sqrt和double乘法,并且您可以优化您的特定应用程序.

正如其他答案所指出的那样,仍然存在大整数的限制,但除非你要遇到这些数字,否则利用浮点硬件支持比编写自己的算法更好.


Val*_*lev 1

哦,今天我需要确定一个数字是否是完美的立方,类似的解决方案非常慢。

所以,我想出了一个非常聪明的替代方案

cubes = map (\x -> x*x*x) [1..]
is_cube n = n == (head $ dropWhile (<n) cubes)
Run Code Online (Sandbox Code Playgroud)

很简单。我想,我需要使用树来更快地查找,但现在我将尝试这个解决方案,也许它对于我的任务来说足够快。如果没有,我将使用正确的数据结构编辑答案