- Published on
- Fri Jan 24, 2014
EPI 5.6 - String to integer conversion functions
Problem ¶
Implement the following methods, which convert (signed) integers to a string and vice versa respectively:
intToString x :: Int -> [Char]
stringToInt :: [Char] -> Int
Additionally invalid strings (when converting to Int) must return an error of some sort.
Solution ¶
Even though the question was specific to converting to and from base 10, this can be generalised to any base with very little changes. The straightforward solution is:
1intToString :: Int -> Int -> [Char]
2intToString base x
3 | x < 0 = "-" ++ intToString base (-x)
4 | x < base = [intToDigit x]
5 | otherwise = (intToString base (div x base)) ++ [intToDigit (mod x base)]
6
7stringToInt :: Int -> [Char] -> Int
8stringToInt base (x:xs)
9 | x == '-' = - (stringIntHelper base xs)
10 | otherwise = stringIntHelper base (x:xs)
11 where stringIntHelper base (x:xs)
12 | dx >= base = error ("Invalid digit: " ++ [x])
13 | length xs == 0 = digitToInt x
14 | otherwise = (dx * (floor (fromIntegral base ** fromIntegral digitsLeft))) + (stringIntHelper base xs)
15 where
16 digitsLeft = (length xs)
17 dx = digitToInt x
Here is an alternative and more intuitive version of stringToIntHelper above:
1stringToIntHelper2 base xs =
2 sum [ digit_to_value digit position |
3 (position, digit) <- (zip dig_positions xs)]
4 where
5 dig_positions = [(length xs) - 1, (length xs) - 2 .. 0]
6 digit_to_value digit position = (digitToInt digit) *
7 floor (base ** fromIntegral position)
This version does not check if each digit is between 0 and “base” but that is a trivial check to add via a “any” check in the original input (xs).