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).