如何获取小数并将其转换为Haskell中的数字列表?

时间:2011-10-08 03:16:58

标签: haskell

我想采取类似1/7(0.142857142857 ...)的东西并将其转换为“0.142857142857”或“142857142857” [1,4,2,8,5,7,1 ,4,2,8,5,7]。使用

map ((+) (-48) . ord) . show

当分母很小但是分母较大时,Haskell开始使用科学记数法。如何将小数字一直转换为数字列表?

4 个答案:

答案 0 :(得分:14)

这不是一个完整的解决方案,但它会让你开始。这将获得0到1之间的数字的数字列表。用适当的方法包装它以获得所需格式的输出。

digits :: (RealFrac a) => a -> [Int]
digits 0 = []
digits x = d : digits (10*x - fromIntegral d)
    where
    d = floor (10*x)

玩弄它:

ghci> digits (1/4)
[2,5]
ghci> digits (1/3)
[3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,3,7,2,7,3,8,6,0,0,9,
 9,9,5,8,2,5,5,8,8,7,0,3,1,5,5,5,1,7,5,7,8,1,2,5]

-- rounding error got us, let's use an exact rational

ghci> import Data.Ratio
ghci> digits (1%3)
[3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
...

当然,您可以从无限的数字列表中获取前缀。

答案 1 :(得分:4)

例如,这将显示1/7到12位小数。它永远不会使用科学记数法。

Numeric.showFFloat (Just 12) (1/7) ""

答案 2 :(得分:1)

我想是直截了当的方式。

showDigits :: Int -> Double -> String
showDigits n x = show (floor x) ++ "." ++ showRest n x

showRest :: Int -> Double -> String
showRest n x | n <= 0 = ""
             | otherwise = digitToInt dig : showRest (pred n) x'
  where dig = (floor x') `mod` 10
        x' = x * 10

但这只能与Double表示一样精确。此外,它永远不会围绕最后的数字;它只是显示它(向下舍入)。测试:

ghci> showDigits 5 (1/7)
"0.14285"

答案 3 :(得分:0)

我想你需要Text.Printf.printf

import Data.Char
import Text.Printf

getDigits :: Double -> [Int]
getDigits=map ((subtract 48).Data.Char.ord) . (Text.Printf.printf "%f")