Haskell/GHC - 有没有办法绕过 Haskell 只返回 16 位小数?
Haskell/GHC - Is there a way around Haskell only returning 16 decimal places?
我正在尝试在 Haskell 中编写一个程序,将 returns 'e
'(欧拉数)保留到给定的小数位。到目前为止,这是我的代码:
factorial 0 = 1
factorial n = n * factorial (n - 1)
calculateE a
| a == 0 = 1
| otherwise = nextLevel
where nextLevel = (1 / (factorial a)) + calculateE (a-1)
每当我调用 calculateE
时,我只会返回 16 位小数。这是 Haskell/My 计算机的限制吗?有没有办法找回任意小数位?
此代码已适用于任意精度。您只需要使用任意精度类型,而不是标准的 Float
/Double
。 Haskell 的标准库有 Rational
用于此目的,它将有理数表示为整数对。
ghci> calculateE 100 :: Rational
4299778907798767752801199122242037634663518280784714275131782813346597523870956720660008227544949996496057758175050906671347686438130409774741771022426508339 % 1581800261761765299689817607733333906622304546853925787603270574495213559207286705236295999595873191292435557980122436580528562896896000000000000000000000000
现在的问题是从中获取数字序列。我不知道标准库中有什么东西可以做到这一点,所以这里有一个愚蠢的简单(可能仍然有问题!)实现:
import Data.List(unfoldr)
import Data.List.NonEmpty(NonEmpty((:|)))
import Data.Ratio
-- first element is integral part (+ sign), rest are positive and < 10 and are digits
-- after the decimal point (for negative numbers, these digits should be seen as having negative value)
longDivision :: Integral a => Ratio a -> NonEmpty a
longDivision x = hi :| unfoldr go (abs lo)
where (hi, lo) = numerator x `quotRem` denominator x
go 0 = Nothing
go lo = Just $ (lo * 10) `quotRem` denominator x
printDigits :: Show a => NonEmpty a -> String
printDigits (x :| xs) = show x ++ "." ++ concatMap show xs
所以
ghci> take 100 $ printDigits $ longDivision $ calculateE 100
"2.71828182845904523536028747135266249775724709369995957496696762772407663035354759457138217852516642"
这个近似值实际上似乎对小数点后 ~160 位很好。
我正在尝试在 Haskell 中编写一个程序,将 returns 'e
'(欧拉数)保留到给定的小数位。到目前为止,这是我的代码:
factorial 0 = 1
factorial n = n * factorial (n - 1)
calculateE a
| a == 0 = 1
| otherwise = nextLevel
where nextLevel = (1 / (factorial a)) + calculateE (a-1)
每当我调用 calculateE
时,我只会返回 16 位小数。这是 Haskell/My 计算机的限制吗?有没有办法找回任意小数位?
此代码已适用于任意精度。您只需要使用任意精度类型,而不是标准的 Float
/Double
。 Haskell 的标准库有 Rational
用于此目的,它将有理数表示为整数对。
ghci> calculateE 100 :: Rational
4299778907798767752801199122242037634663518280784714275131782813346597523870956720660008227544949996496057758175050906671347686438130409774741771022426508339 % 1581800261761765299689817607733333906622304546853925787603270574495213559207286705236295999595873191292435557980122436580528562896896000000000000000000000000
现在的问题是从中获取数字序列。我不知道标准库中有什么东西可以做到这一点,所以这里有一个愚蠢的简单(可能仍然有问题!)实现:
import Data.List(unfoldr)
import Data.List.NonEmpty(NonEmpty((:|)))
import Data.Ratio
-- first element is integral part (+ sign), rest are positive and < 10 and are digits
-- after the decimal point (for negative numbers, these digits should be seen as having negative value)
longDivision :: Integral a => Ratio a -> NonEmpty a
longDivision x = hi :| unfoldr go (abs lo)
where (hi, lo) = numerator x `quotRem` denominator x
go 0 = Nothing
go lo = Just $ (lo * 10) `quotRem` denominator x
printDigits :: Show a => NonEmpty a -> String
printDigits (x :| xs) = show x ++ "." ++ concatMap show xs
所以
ghci> take 100 $ printDigits $ longDivision $ calculateE 100
"2.71828182845904523536028747135266249775724709369995957496696762772407663035354759457138217852516642"
这个近似值实际上似乎对小数点后 ~160 位很好。