开发者

haskell power function

开发者 https://www.devze.com 2023-03-01 18:13 出处:网络
how to write a power function which makes use of the following facts: To raise x to a power n (where n is a positive whole number), if nis even, you can find the nth power of x by squaring half that p

how to write a power function which makes use of the following facts: To raise x to a power n (where n is a positive whole number), if n is even, you can find the nth power of x by squaring half that power. For example, x^12 is x^6 * x^6. For odd powers, just subtract one from the power, and multiply the result for the smaller power by x. for example, x^13 is x * x^12, which is x * x^6 * x^6. Recursively, any power can be found with less work than m开发者_如何学运维ultiplying x by itself the number of times indicated. I came up with this

power x n
    | n == 0  =  1
    | x == 0  =  0
    | even n = ( power x (n / 2) ) * ( power x (n / 2) )
    | odd n = x * ( power x ((n - 1) / 2)) * ( power x ((n - 1) / 2) )

but I get an error saying ERROR - Unresolved overloading * Type : (Integral a, Fractional a) => Integer * Expression : power 2 2


What's happened here is a common type mismatch. First, take a look at the type signature for even: even :: (Integral a) => a -> Bool. odd has a similar signature. So you can see that even and odd take any type of the Integral typeclass and evaluate it. Then look at the signature for /: (/) :: (Fractional a) => a -> a -> a. / takes only Fractional types, not Integral ones. It's impossible for one type to be evaluated by both those functions. In this case, there's an easy fix: use div instead of /. Note that if you use div as an infix function (place it between the arguments) you'll need to put backticks around div.


Look at the type of even and compare that to the type of /.


Just a remark now that your code is running: Haskell doesn't automatically memoize functions, so you're calculating the recursive calls to power twice in the last two lines. I would recommend to introduce a simple function sqr k = k * k and to use it. There are several ways: a separate function; a where clause; and let.

I would prefer let:

power _ 0 = 1
power 0 _ = 0
power x n  = let sqr k = k * k
                 half_n = n `div` 2  
                 sqrHalfPower = sqr ( power x half_n )
             in if even n then sqrHalfPower else x * sqrHalfPower 

As you can see pattern matching deals with the first two cases. Then let defines some useful expressions, which can be used later in in. Note that for odd numbers, (n-1) `div` 2 gives the same result as n `div` 2, so we can unify both cases.


I think, the fastest way to calculate power:

     pow:: Integer->Integer->Integer
     pow x n  |(n==1) = x
              |even n = (pow x ( div n 2))*(pow x ( div n 2)) 
              |odd n  = x * (pow x (n-1))

you can also use "Int" instead "Integer"(replace Integer on Int in the signature!).

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号