package multiplystrings func addDigits(a, b byte) (byte, byte) { abInt := int(a-'0') + int(b-'0') return byte(abInt/10) + '0', byte(abInt%10) + '0' } func addByDigit(dst *[]byte, src byte) { for i, b := range *dst { if src == '0' { return } src, (*dst)[i] = addDigits(b, src) } if src != '0' { *dst = append(*dst, src) } } func add(dst *[]byte, src []byte) { carry := byte('0') for i := range max(len(*dst), len(src)) { d, s := byte('0'), byte('0') if len(*dst) > i { d = (*dst)[i] } if len(src) > i { s = src[i] } hi, lo := addDigits(d, s) total := []byte{lo, hi} addByDigit(&total, carry) (*dst)[i], carry = total[0], total[1] } if carry != '0' { *dst = append(*dst, carry) } } func multiplyDigits(a, b byte) (byte, byte) { abInt := int(a-'0') * int(b-'0') return byte(abInt/10) + '0', byte(abInt%10) + '0' } func multiplyByDigit(and []byte, ier byte) []byte { result, carry := []byte{}, byte('0') for _, b := range and { hi, lo := multiplyDigits(b, ier) // Fold the incoming carry into the low digit; any overflow rolls // into hi, which is small enough that it never overflows again. c, lo := addDigits(lo, carry) _, carry = addDigits(hi, c) result = append(result, lo) } if carry != '0' { result = append(result, carry) } return result } func reverse(s string) []byte { digits := make([]byte, len(s)) for i := range s { digits[len(s)-1-i] = s[i] } return digits } func multiply(a, b string) string { if a == "0" || b == "0" { return "0" } and := reverse(a) result := make([]byte, len(a)+len(b)) for i := range result { result[i] = '0' } for i := range len(b) { ier := b[len(b)-1-i] partial := multiplyByDigit(and, ier) // Shift left by i places (little-endian: i leading zeros). shifted := make([]byte, i+len(partial)) for j := range i { shifted[j] = '0' } copy(shifted[i:], partial) add(&result, shifted) } end := len(result) for end > 1 && result[end-1] == '0' { end-- } out := make([]byte, end) for i := range end { out[i] = result[end-1-i] } return string(out) }