Decimal is not the only base worth reading. Hexadecimal output is just repeated division by sixteen, collecting remainders - a direct use of the short division you built. Today you add Hex.
Render a BigInt as a lowercase hexadecimal string via repeated division by sixteen.
Converting to another base is repeated division by that base, reading the remainders
off from least significant to most. For hex, divide the magnitude by 16 over and
over; each remainder is a value from 0 to 15, one hexadecimal digit. Because the
digits come out lowest first, you reverse the collected string at the end, then
prepend a - if the number is negative and print "0" for zero.
This reuses divScalar unchanged - 16 is a perfectly ordinary single-limb divisor -
which is why building division early pays off now. 255 is "ff", 4096 is
"1000", and 2^64 is 1 followed by sixteen zeros, exactly the fixed-width hex you
would expect but with no width limit. Parsing hex back in is the inverse, and the last
new operation before the capstone.
const hexDigits = "0123456789abcdef"func (x BigInt) Hex() string {if x.sign == 0 { return "0" }m := x.magvar out []bytefor len(m) > 0 {var d uint32m, d = divScalar(m, 16) // remainder is the next hex digitout = append(out, hexDigits[d])}// reverse out, prepend '-' when negative}