Non-decimal radices/Convert: Difference between revisions

m
(→‎{{header|Haskell}}: Deriving toBase :: Int -> Int -> String from inBaseDigits :: [Char] -> Int -> String)
Line 1,227:
 
Using built-in functions to convert integer into string, and vice versa, at any base up to 16:
 
<lang haskell>Prelude> Numeric.showIntAtBase 16 Char.intToDigit 42 ""
"2a"
Prelude> fst $ head $ Numeric.readInt 16 Char.isHexDigit Char.digitToInt "2a"
42</lang>
 
It's actually more useful to represent digits internally as numbers instead of characters, because then one can define operations that work directly on this representation.
 
So conversion to and from digits represented as 0-9 and a-z is done in an additional step.
 
<lang haskell>import Data.List
import Data.Char
 
toBase :: Int -> Int -> [Int]
toBase b v = toBase' [] v where
toBase' a 0 = a
toBase' a v = toBase' (r:a) q where (q,r) = v `divMod` b
 
fromBase :: Int -> [Int] -> Int
fromBase b ds = foldl' (\n k -> n * b + k) 0 ds
 
toAlphaDigits :: [Int] -> String
toAlphaDigits = map convert where
convert n | n < 10 = chr (n + ord '0')
| otherwise = chr (n + ord 'a' - 10)
 
fromAlphaDigits :: String -> [Int]
fromAlphaDigits = map convert where
convert c | isDigit c = ord c - ord '0'
| isUpper c = ord c - ord 'A' + 10
| isLower c = ord c - ord 'a' + 10</lang>
 
Example:
 
<lang haskell>*Main> toAlphaDigits $ toBase 16 $ 42
"2a"
*Main> fromBase 16 $ fromAlphaDigits $ "2a"
42</lang>
 
 
Or, allow for digit variants like upper case vs lower case Hexadecimal, we can express our conversion function(s) in terms of a more general '''inBaseDigits''' function which, given an ordered list of digits as its first argument, returns an Int -> String unfold function. (The base is the length of the digit list).
 
If we want to assume a default character set, then a general '''toBase''' (Int -> Int -> String) can be also be derived from '''inBaseDigits'''.
 
<lang haskell>import Data.List (unfoldr)
Line 1,280 ⟶ 1,237:
else []
 
inBaseDigits :: [Char]String -> Int -> String
inBaseDigits ds n =
let base = length ds
Line 1,314 ⟶ 1,271:
11111110
376
fe</pre>
11111110</pre>
 
=={{header|HicEst}}==
9,655

edits