build-a-bignum-library / lesson-04.md
Lesson 04 · Limbs, sign, and decimal I/O

Parsing a decimal magnitude

Base 1000000000 was chosen for exactly this moment - nine decimal digits are one limb, so parsing a decimal string means slicing it into nine-digit groups from the right. Today you turn a run of digits into a magnitude.

The goal

Parse a string of decimal digits into a magnitude by grouping nine digits per limb from the right.

Start here - the target
TO DO
Scenario: A decimal string groups into limbs nine digits at a time from the right
Giventhe decimal string "12345678901234567890"
Whenit is parsed into a magnitude
Thenit has 3 limbs: limb 0 is 234567890, limb 1 is 345678901, and limb 2 is 12
Andthe string "5" parses to one limb of value 5, and "1000000000" parses to limbs (0, 1)
Background

Here is the payoff of base 1000000000: a limb holds a number from 0 to 999999999, which is precisely the range of a nine-digit decimal group. So to parse a decimal string you do not need any multiplication at all - you cut the string into nine-digit pieces from the right, and each piece, read as an ordinary integer, is one limb. The rightmost nine digits are limb 0, the next nine are limb 1, and a short leftover chunk (here 12) is the top limb.

The only subtlety is the leftmost chunk, which may be shorter than nine digits, so your cut has to clamp at the start of the string. Run the result through normalize so a string like "000000000" collapses to the empty magnitude. Signs and bad input are the next lesson; today assume the string is a clean run of digits.

Make it work
// walk the string from the right in chunks of nine digits
func parseMag(s string) mag {
var m mag
for len(s) > 0 {
cut := len(s) - 9
if cut < 0 { cut = 0 }
limb := atoiUint(s[cut:]) // parse this <=9 digit chunk
m = append(m, uint32(limb))
s = s[:cut]
}
return m.normalize()
}
CheckpointDONE
A decimal string becomes a magnitude by nine-digit grouping. Commit and stop here.