Home > Blockchain >  Splitting big.Int by digit
Splitting big.Int by digit

Time:11-15

I'm trying to split a big.Int into a number of int64s 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?

CodePudding user response:

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
}

Multiplying each output by input.Sign() ensures that each output will be negative if the input is negative. The sum of the output values multiplied by 1e18 times their position in the output should equal the input.

  •  Tags:  
  • go
  • Related