微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Haskell / GHC-有办法解决Haskell仅返回16位小数的问题吗?

如何解决Haskell / GHC-有办法解决Haskell仅返回16位小数的问题吗?

我试图在Haskell中编写一个程序,该程序将'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 /我的计算机的限制吗?有没有办法找回任意数量的小数位?

解决方法

此代码已经可以任意精度工作了。您只需要使用任意精度类型,而不是标准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位数字似乎很好。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。