Splitting big.Int by digit

Issue

I’m trying to split a `big.Int` into a number of `int64`s such that each is a portion of the larger number, with a standard offset of 18 digits. For example, given the following input value of `1234512351234088800000999`, I would expect the following output: `[351234088800000999, 1234512]`. For negative numbers, I would expect all of the parts to be negative (i.e. `-1234512351234088800000999` produces `[-351234088800000999, -1234512]`).

I already know I can do this to get the result I want:

``````func Split(input *big.Int) []int64 {
const width = 18

asStr := in.Coefficient().Text(10)
strLen := len(asStr)
offset := 0
if in.IsNegative() {
offset = 1
}

length := int(math.Ceil(float64(strLen-offset) / width))
ints := make([]int64, length)
for i := 1; i <= length; i++ {
start := strLen - (i * width)
end := start + width
if start < 0 || (start == 1 && asStr[0] == '-') {
start = 0
}

ints[i-1], _ = strconv.ParseInt(asStr[start:end], 10, 64)
if offset == 1 && ints[i-1] > 0 {
ints[i-1] = 0 - ints[i-1]
}
}

return ints
}
``````

However, I don’t like the idea of using string-parsing nor do I like the use of `strconv`. Is there a way I can do this utilizing the `big.Int` directly?

Solution

You can use the `DivMod` function to do what you need here, with some special care to handle negative numbers:

``````var offset = big.NewInt(1e18)

func Split(input *big.Int) []int64 {
rest := new(big.Int)
rest.Abs(input)

var ints []int64
r := new(big.Int)
for {
rest.DivMod(rest, offset, r)
ints = append(ints, r.Int64() * int64(input.Sign()))
if rest.BitLen() == 0 {
break
}
}
return ints
}
``````

Note that it’s not clear exactly what should happen for negative numbers. Depending on what you want, you might want to just flip the sign on the first output, or the last, or something else. In the code here, I make all the output values negative if the input was negative so that the sum of the output values multiplied by 1e18 times their position in the output equals the input.

Answered By – Austin

Answer Checked By – Terry (GoLangFix Volunteer)