Personal tools

Haskell Quiz/Internal Rate of Return/Solution Dolio

From HaskellWiki

< Haskell Quiz | Internal Rate of Return(Difference between revisions)
Jump to: navigation, search
(creation)
 
(use until instead of iterate)
 
(One intermediate revision by one user not shown)
Line 1: Line 1:
  +
[[Category:Haskell Quiz solutions|Internal Rate of Return]]
  +
 
My solution for this quiz uses the [http://en.wikipedia.org/wiki/Secant_method secant method], which is quite easy to implement.
 
My solution for this quiz uses the [http://en.wikipedia.org/wiki/Secant_method secant method], which is quite easy to implement.
   
Line 7: Line 9:
   
 
secant :: (Double -> Double) -> Double -> Double
 
secant :: (Double -> Double) -> Double -> Double
secant f delta = fst . head . dropWhile err . iterate update $ (0,1)
+
secant f delta = fst $ until err update (0,1)
 
where
 
where
 
update (x,y) = (x - (x - y)*(f x)/(f x - f y), x)
 
update (x,y) = (x - (x - y)*(f x)/(f x - f y), x)
err (x,y) = abs (x - y) > delta
+
err (x,y) = abs (x - y) < delta
   
 
npv :: Double -> [Double] -> Double
 
npv :: Double -> [Double] -> Double

Latest revision as of 13:41, 9 February 2008


My solution for this quiz uses the secant method, which is quite easy to implement.

import Data.Function
import Numeric
import System.Environment
 
secant :: (Double -> Double) -> Double -> Double
secant f delta = fst $ until err update (0,1)
 where
 update (x,y) = (x - (x - y)*(f x)/(f x - f y), x)
 err (x,y) = abs (x - y) < delta
 
npv :: Double -> [Double] -> Double
npv i = sum . zipWith (\t c -> c / (1 + i)**t) [0..]
 
main = do (s:t) <- getArgs
          let sig = read s
              cs = map read t
          putStrLn . ($"") . showFFloat (Just sig) $ secant (flip npv cs) (0.1^sig)

The resulting program expects the first argument to be the number of digits to be displayed after the decimal point, while the rest are the yearly income. For instance:

   ./IRR 4 -100 30 35 40 45
   0.1709