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.
108 lines
3.3 KiB
108 lines
3.3 KiB
8 months ago
|
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
|
||
|
}
|