这就是问题所在:声明类型并定义一个函数,该函数将 2 个正数(例如 m 和 n)作为输入,并将 m 提高到 n 次方。请仅使用递归。不要使用幂运算符或库函数,只需使用递归。
到目前为止,这是我的代码:
sqr :: Int -> Int -> Int
平方米
| m > 0 && n > 0 = sqr (m * m) (n - 1) | otherwise = m
出于某种原因,当我执行 sqr 10 2 时,它给了我 1000 之类的值。有谁知道我做错了什么?
让我们展开。此外,您的函数应该被调用pow
,而不是sqr
,但这并不重要。
sqr 10 2 = sqr (10 * 10) (2 - 1)
= sqr 100 1
= sqr (100 * 100) (1 - 1)
= sqr 10000 0
= 10000
这说明了为什么sqr 10 2 = 10000
。
每次递归时, 都有不同的值m
。所以你需要以某种方式考虑到这一点:
要么你编写一个即使m
每次都有不同的值也能工作的版本,或者,
你找到一种方法来保持原来的值m
左右。
我想说最简单的方法是使用m^n = m * m^(n-1)
, 和m^0 = 1
.
如果你很聪明,有一种方法更快,它也依赖于m^2n = (m^n)^2
.
我上面写的一些数学公式实际上是有效的 Haskell 代码。
import Prelude hiding ((^))
infixr 8 ^
(^) :: Int -> Int -> Int
-- Do these two lines look familiar?
m^0 = 1
m^n = m * m^(n-1)
这只是函数的中缀版本。您可以将中缀运算符更改为普通函数,
pow :: Int -> Int -> Int
pow m 0 = 1
pow m n = m * pow m (n - 1)
还有更快的版本:
pow :: Int -> Int -> Int
pow m 0 = 1
pow m n
| even n = x * x where x = pow m (n `quot` 2)
| otherwise = m * pow m (n - 1)
这里有两个单独的问题。只需写出所有术语重写步骤,看看它们是什么:
sqr 10 2
sqr (10 * 10) (2 - 1)
sqr 100 (2 - 1)
sqr 100 1
sqr (100 * 100) (1 - 1)
sqr 10000 (1 - 1)
sqr 10000 0
10000
这将清楚地向您显示其中一个问题。如果您还没有看到另一个,请尝试从
sqr 10 3