\(e^x\)를 계산하기
\(e ^ x\)는 다음 식으로 계산된다.
$$ 1 + x + x^2/2! + x^3/3! ... $$
이계산을 10단계까지 확장한 값을 계산하는 프로그램을 작성하라
여기서 헷갈리기 쉬운 것이 바로 Double
타입과 Int
타입간의 연산이다. 두 타입은 엄격히 다르며, 하스켈은 자동 형변환을 지원하지 않기 때문에 1.0 + 3
같은 표현식은 에러가 난다.
물론 이 식을 REPL에서
> 1.5 + 3
하면 4.5로 계산하는데 이는 REPL이 뒤의 3을Double
타입으로 읽었기 때문이다. 타입을 명시해서> 1.5 + (3::Int)
라고 적시하는 경우에는 에러로 처리된다.
문제에서 주어진 식은 k=0,1,2,.... 일 때 $x^k/k!$를 계산하는 것이니, 간단한 함수를 하나 만들면 된다. 그전에 팩토리얼을 계산할 함수를 하나 작성하자.
fact :: Int -> Double
fact n
| n < 2 = 1
| otherwise = fromIntegral . foldr1 (*) [2..n]
두 번째는 power
연산 ( a의 b 승)을 구하는 것인데, 하스켈에서 이 연산은 오버로딩되어 있지 않고 다음과 같이 명시적으로 분리되어 있다. (https://wiki.haskell.org/Power_function)
(^) :: (Num a, Integral b) => a -> b -> a
(^^) :: (Fractional a, Integaral b) => a -> b -> a
(**) :: (Floating a) => a -> a -> a
밑이 실수인 경우에는 ^^
를, 지수도 실수인 경우에는 **
를 쓰는 것이 일반적이며 둘 다 정수일 때만 ^
를 쓴다고 알아두자.
거듭제곱값과 팩토리얼 값을 나눠야 하기 때문에 fact
함수는 최종적으로 fromIntegral
함수를 이용해서 실수 값으로 변환해둔다.
이제 solve
함수를 작성해보자.
solve :: Double -> Double
solve x = sum [(x^^k) / (fact k) | k <- [0..9]
여기까지 진행했으면 solve
함수의 구현이 별로 어렵지는 않을 것이다.
최종 결과를 보자
import Control.Applicative
import Control.Monad
import System.IO
fact :: Int -> Double
fact n
| n < 2 = 1
| otherwise = fromIntegral . foldr1 (*) $ [2..n]
solve :: Double -> Double
solve x = sum[ (x^^k) / (fact k) | k <- [0..9]]
main :: IO ()
main = do
l <- readLn :: IO Int
forM_ [1..n] $ \a0 -> do
xtemp <- getLine
let x = read xtemp :: Double
putStrLn . show . solve $ x