| 1 | module Decimal |
|---|
| 2 | ( digits, number |
|---|
| 3 | , d10 |
|---|
| 4 | , inInterval |
|---|
| 5 | ) |
|---|
| 6 | where |
|---|
| 7 | |
|---|
| 8 | import Debug.Trace |
|---|
| 9 | import Data.Ratio |
|---|
| 10 | |
|---|
| 11 | import Test.QuickCheck |
|---|
| 12 | |
|---|
| 13 | digits :: Integral a => a -> Ratio a -> Ratio a -> [a] |
|---|
| 14 | digits base lo hi = |
|---|
| 15 | if r dplus < r base * hi then |
|---|
| 16 | if dplus == 0 then [] else [dplus] |
|---|
| 17 | else d0 : digits base (expand lo) (expand hi) |
|---|
| 18 | where dplus = myceil (r base * lo) |
|---|
| 19 | d0 = dplus - 1 |
|---|
| 20 | expand x = r base * x - r d0 |
|---|
| 21 | r = fromIntegral |
|---|
| 22 | myceil r = (n + d - 1) `div` d |
|---|
| 23 | where (n, d) = (numerator r, denominator r) |
|---|
| 24 | |
|---|
| 25 | number :: Integral a => a -> [a] -> Ratio a |
|---|
| 26 | number base [] = 0 |
|---|
| 27 | number base (d:ds) = (fromIntegral d + number base ds) / fromIntegral base |
|---|
| 28 | |
|---|
| 29 | |
|---|
| 30 | inInterval base (NonNegative num) (Positive den) = ok |
|---|
| 31 | where x' = number base (digits base (num % den) (inc num % den)) |
|---|
| 32 | x = num % den |
|---|
| 33 | x1 = inc num % den |
|---|
| 34 | ok = x <= x' && x' < x1 |
|---|
| 35 | inc n = n + 1 |
|---|
| 36 | |
|---|
| 37 | minimalLength base (NonNegative num) (Positive den) = not (null ds) ==> ok |
|---|
| 38 | where x' = number base (init ds) |
|---|
| 39 | ds = digits base (num % den) (inc num % den) |
|---|
| 40 | x = num % den |
|---|
| 41 | x1 = inc num % den |
|---|
| 42 | ok = not (x <= x' && x' < x1) |
|---|
| 43 | inc n = n + 1 |
|---|
| 44 | |
|---|
| 45 | |
|---|
| 46 | d10 n d = digits 10 (n % d) ((n + 1) % d) |
|---|