Haskell中的整数平方根函数

Haskell中的整数平方根函数,haskell,recursion,Haskell,Recursion,正整数n的整数平方根是平方为的最大整数 小于或等于n。(例如,7的整数平方根是2,9的整数平方根是3) 以下是我的尝试: intSquareRoot :: Int -> Int intSquareRoot n | n*n > n = intSquareRoot (n - 1) | n*n <= n = n intSquareRoot::Int->Int 平方根 |n*n>n=intSquareRoot(n-1) |n*n您可能没有可编辑的变量,但可以递

正整数n的整数平方根是平方为的最大整数 小于或等于n。(例如,7的整数平方根是2,9的整数平方根是3)

以下是我的尝试:

intSquareRoot :: Int -> Int
intSquareRoot n
    | n*n > n   = intSquareRoot (n - 1) 
    | n*n <= n  = n
intSquareRoot::Int->Int
平方根
|n*n>n=intSquareRoot(n-1)

|n*n您可能没有可编辑的变量,但可以递归地传递参数

intSquareRoot :: Int -> Int
intSquareRoot n = try n where
  try i   | i*i > n   = try (i - 1) 
          | i*i <= n  = i
。。。但是由于这是Haskell,你不能使用变量来保持原来的n

我不知道你为什么这么说。以下是您可以如何实现它:

intSquareRoot :: Int -> Int
intSquareRoot n = aux n
  where
    aux x
      | x*x > n = aux (x - 1)
      | otherwise = x
这已经足够好了,但它不是一个非常有效的实现。可以在以下网站上找到更好的:

(^!)::Num a=>a->Int->a
(^!)xn=x^n
平方根::整数->整数
平方根0=0
平方根1=1
平方根n=
让twopows=迭代(^!2)2
(洛维罗,洛维恩)=
最后$takeWhile((n>=).snd)$zip(1:twopows)twopows
新步骤x=div(x+divnx)2
iters=迭代新步骤(平方根(div n lowerN)*lowerRoot)

isRoot r=r^!2您最初的尝试,以及用户2989737的良好更正,尝试从n到解决方案的每个数字。对于大的数字,它是非常慢的,复杂性是O(n)。最好从0开始到解决方案,这将复杂性提高到O(sqrt n):

intSquareRoot::Int->Int
intSquareRoot n=尝试0,其中

尝试i | i*i由于在每个递归调用中重叠了
n
参数,因此建议的解决方案不起作用

以下解决方案使用二进制搜索并在
O(log(n))
中查找整数平方根:


在每次递归调用(
[a,m)
[m,b)
)时,将范围
[a,b)
除以2,这取决于平方根所在的位置。

我不太清楚您打算如何工作。假设您有一个单独的变量r(表示根)然后开始比较
r*r
n
,你会尝试r的值是多少?你会如何让Haskell知道?老实说,我真的不知道我是否朝着正确的方向去解决这个问题!我在Haskell比较新,这是我第一次尝试解决这个问题,任何其他解决方法都会非常感谢!那太感谢了!我对这个问题的理解是空白的,完全忘记了我可以使用“where”!它与
intSqrt=floor.sqrt.fromInteger
相比如何?@kqr我在Haskell的wiki上发布的链接解释了为什么这种方法有问题:1)舍入问题会导致错误的结果;2)整数有错误任意精度,而浮点数则不是-这意味着将其转换为浮点数可能会失败,并出现溢出错误、无穷大或不精确的值。
intSquareRoot :: Int -> Int
intSquareRoot n = aux n
  where
    aux x
      | x*x > n = aux (x - 1)
      | otherwise = x
(^!) :: Num a => a -> Int -> a
(^!) x n = x^n

squareRoot :: Integer -> Integer
squareRoot 0 = 0
squareRoot 1 = 1
squareRoot n =
   let twopows = iterate (^!2) 2
       (lowerRoot, lowerN) =
          last $ takeWhile ((n>=) . snd) $ zip (1:twopows) twopows
       newtonStep x = div (x + div n x) 2
       iters = iterate newtonStep (squareRoot (div n lowerN) * lowerRoot)
       isRoot r  =  r^!2 <= n && n < (r+1)^!2
  in  head $ dropWhile (not . isRoot) iters
intSquareRoot :: Int -> Int
intSquareRoot n = try 0 where
  try i   | i*i <= n    = try (i + 1) 
          | True        = i - 1
squareRoot :: Integral t => t -> t
squareRoot n 
   | n > 0    = babylon n
   | n == 0   = 0
   | n < 0    = error "Negative input"
   where
   babylon a   | a > b  = babylon b
               | True   = a
      where b  = quot (a + quot n a) 2
intSquareRoot :: Int -> Int
intSquareRoot n = bbin 0 (n+1)
    where bbin a b | a + 1 == b = a
                   | otherwise = if m*m > n
                                 then bbin a m
                                 else bbin m b
                               where m = (a + b) `div` 2