2017-05-27

Parsing a number into digits - Reprise

blogentry, programming, c, digits

banner

Featured Image - "Numbers" by Kevin Dooley, used under CC BY 2.0

On 3/11/2017, I wrote a blog entry Parsing a Number into Digits. While it's not hard to implement the method to parse a number into digits, I wanted a simpler way for quick tests.

After solving a problem, Recursive Digit Sum, I fiddled around with a few different ways.

I will discuss the implementation as well as dis/advantage of it.

Before posting the 3/11 blog, I used to parse each digit at a time using int.Parse().

1private static IEnumerable<int> GetArray2(int value)2{3	if (value < 0) value = -1; // or Math.Abs4
5	string text = value.ToString();6	for (int i = 0; i < text.Length; i++)7	{8		yield return int.Parse(text\[i\].ToString());9	}10}

While reading the problem discussion forum, I ran into this GO implementation of digit sum of a number by sei40kr. I noticed that he simply subtracted a number character by '0'. It's just a simple ASCII algebra but that thought never occurred to me.

By the way, here is how the ASCII subtraction works.

E.g.) Ascii value of '1' is 49, '0' is 48, '2' is 50 and '9' is 57.  So basically subtracting an ASCII value of current number character with '0' becomes the number.

'1' - '0' = 1 (49 - 48) '2' - '0' = 2 (50 - 48) ... '9' - '0' = 9 (57 - 48)

This implementation was faster than the "int.parse" one but still slower than the stack version. But the advantage is that it's easier to implement, more intuitive thus less error prone.

The implementation is the same as GetArray2 and the only difference is that GetArray3 returns an integer using subtraction (line# 8).

1private static IEnumerable<int> GetArray3(int value)2{3if (value < 0) value = -1; // or Math.Abs4
5    string text = value.ToString();6    for (int i = 0; i < text.Length; i++)7    {8    	yield return text\[i\] - '0';9    }10}

ASCII subtraction version is about 2~3 times faster than the int.parse version.

Conclusion

For a quick testing, I'd use the int.parse version but for production code, I'd use the stack implementation.

While the former is easier to implement and less error prone, the latter is still much faster by the fact of two (Stack version is about 5~6 times faster than int.parse version).

A contrived benchmarking result came out as follows.

Implementation using Stack: 00:00:04.0093535 Implementation using int.parse: 00:00:22.2908904 Implementation using ordinal number: 00:00:08.3212206

The source for this test is on GitHub.