You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
lavos/cap3/ex18.go

108 lines
3.3 KiB

package cap3
import (
"strings"
)
// Ex18 超长整数乘法(都超长)
func Ex18(a, b string) string {
result := make([]uint8, len(a)+len(b))
resultEndIdx := len(result) - 1
for i := 0; i < len(b); i++ {
carry := uint8(0)
aEnd, bEnd, resultIdx := len(a)-1, len(b)-1, 0
bDigit := b[bEnd-i] - 48
for j := 0; j < len(a); j++ {
// 字符转数字
aDigit := a[aEnd-j] - 48
// 当前位计算结果 = 当前结果 + aDigit*bDigit + 进位
resultIdx = resultEndIdx - (i + j)
num := result[resultIdx] + aDigit*bDigit + carry
// 当前位为计算结果的个位,进位为十位上的数字
result[resultIdx] = num % 10
carry = num / 10
}
// 如果还有进位,则对下一个结果位添加进位,此时不会再有进位
if carry != 0 {
resultIdx--
result[resultIdx] += carry
}
}
zeroPrefix := true
sb := strings.Builder{}
for _, num := range result {
if zeroPrefix && num == 0 {
continue
} else {
zeroPrefix = false
}
sb.WriteByte(num + 48)
}
return sb.String()
}
// Ex18type2 超长整数乘法(都超长),a和b都是大端序的数字数组/切片
func Ex18type2(a, b []uint8) []uint8 {
result := make([]uint8, len(a)+len(b))
resultEndIdx := len(result) - 1
for i := 0; i < len(b); i++ {
carry := uint8(0)
aEnd, bEnd, resultIdx := len(a)-1, len(b)-1, 0
bDigit := b[bEnd-i]
for j := 0; j < len(a); j++ {
// 字符转数字
aDigit := a[aEnd-j]
// 当前位计算结果 = 当前结果 + aDigit*bDigit + 进位
resultIdx = resultEndIdx - (i + j)
num := result[resultIdx] + aDigit*bDigit + carry
// 当前位为计算结果的个位,进位为十位上的数字
result[resultIdx] = num % 10
carry = num / 10
}
// 如果还有进位,则对下一个结果位添加进位,此时不会再有进位
if carry != 0 {
resultIdx--
result[resultIdx] += carry
}
}
return result
}
// Ex18type3 超长整数乘法(都超长),a是大端序的数字数组/切片,b为uint64
func Ex18type3(a []uint8, b uint64) []uint8 {
result := make([]uint8, len(a)+22)
resultEndIdx := len(result) - 1
bOffset := 0
for i := b; i >= 1; i /= 10 {
carry := uint8(0)
bDigit := uint8(i % 10)
aEnd, resultIdx := len(a)-1, 0
for j := 0; j < len(a); j++ {
// 字符转数字
aDigit := a[aEnd-j]
// 当前位计算结果 = 当前结果 + aDigit*bDigit + 进位
resultIdx = resultEndIdx - (bOffset + j)
num := result[resultIdx] + aDigit*bDigit + carry
// 当前位为计算结果的个位,进位为十位上的数字
result[resultIdx] = num % 10
carry = num / 10
}
// 如果还有进位,则对下一个结果位添加进位,此时不会再有进位
if carry != 0 {
resultIdx--
result[resultIdx] += carry
}
bOffset++
}
return result
}