Infinite lazy lists of digits
Asked Answered
G

2

6

So I'm trying to do some number theory work, and I was using Mathematica but thought that Haskell would be more suited to dealing with infinite lists (as AFAIK Mathematica doesn't have lazy evaluation). What I want to do is have Haskell store all the digits of 1/x in an infinite lazy list. So far my searching has not turned up a way to split a ratio into its digits that returns a list of digits rather than an actual floating point number.

Ganister answered 14/1, 2014 at 20:40 Comment(6)
This might be helpful #805434Ravioli
@Ravioli is pointing in the right direction. Before you get into the bit-fiddly stuff, however, remember that Haskell has very good built-in bignum support: the Integer type. It may still be necessary to fiddle bits, but it may not. Remember to use quotrem instead of divmod whenever possible.Coolant
You may find this StackExchange post interesting: “Functional style using lazy lists?”: mathematica.stackexchange.com/questions/838/… The question inspired Mathematica package which is referenced in one of the answers.Subastral
@SamYonnou, that page had the answer I needed. Thanks. Final code was: nDigRat :: Int -> Int -> Int -> Int nDigRat num denom n = floor (fromIntegral (10*(10^(n-1)*num `rem` denom)) / fromIntegral denom) `rem` 10 decExpansionRecipRat :: Int -> [Int] decExpansionRecipRat n = map (nDigRat 1 n) [1..]`Ganister
kocho - you should post that as an answer so it's easier to readChancechancel
It doesn't address your question directly, but Conal Elliott's blog entry on adding infinite digit lists might be worth a read.Prenatal
E
6

We can also implement this as a simple stream producer:

divDigits :: Int -> Int -> [Int]
divDigits x y = x `div` y : divDigits (10 * (x `mod` y)) y

There are actually libraries for this kind of "infinite"-precision number representation using lazy lists, see Haskell Wiki.

Elnora answered 15/1, 2014 at 15:34 Comment(0)
G
2

Big thanks to Sam Yonnou, the link he provided had the right formula
The formula used:
the nth digit of x/y is the 1st digit of (10^(n-1)*x mod y)/y = floor(10 * (10^(n-1)*x mod y) / y) mod 10

The ending code looked like this:

nDigRat :: Int -> Int -> Int -> Int
nDigRat num denom n = floor (fromIntegral (10*(10^(n-1)*num `rem` denom)) / 
                             fromIntegral denom) 
                      `rem` 10

decExpansionRecipRat :: Int -> [Int]
decExpansionRecipRat n = map (nDigRat 1 n) [1..]
Ganister answered 15/1, 2014 at 6:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.