算法 - 高精度算法(加减乘除)-算法思路

  • 和高精度加法差不多
  • 新建整数t=0,用于保存借位
  • 将各个位置上的数进行相减,得出每一位的结果和借位值

代码

package main

import (
	"fmt"
)

// 判断是否有A>=B
func cmp(A, B []int) bool {
	if len(A) != len(B) {
		return len(A) > len(B)
	}

	for i := 0; i < len(A); i++ {
		if A[i] != B[i] {
			return A[i] > B[i]
		}
	}
	return true
}

func Sub(A, B []int) {
	C := make([]int, 0)

	for i, t := 0, 0; i < len(A); i++ {
		t = A[i] - t
		if i < len(B) {
			t -= B[i]
		}
		C = append(C, (t+10)%10)
		if t >= 0 {
			t = 0
		} else {
			t = 1
		}
	}
	for len(C) > 1 && C[len(C)-1] == 0 {
		C = C[:len(C)-1]
	}
	for i := len(C) - 1; i >= 0; i-- {
		fmt.Print(C[i])
	}
}

func main() {
	var a, b string
	fmt.Scanf("%s %s", &a, &b)
	A, B := make([]int, len(a)), make([]int, len(b))
	for i := len(a) - 1; i >= 0; i-- {
		A[len(a)-1-i] = int(a[i] - 48)
	}
	for i := len(b) - 1; i >= 0; i-- {
		B[len(b)-1-i] = int(b[i] - 48)
	}

	if cmp(A, B) {
		Sub(A, B)
	} else {
		fmt.Print("-")
		Sub(B, A)
	}
}

需要注意的点

  • 相减为负数的处理
    • 需要对a,b的大小进行判断。若a>=b则为正整数,无需处理;若a<b则为负数,需要在输出时加前导"-"
  • 前导0的处理
    • 在得出逆序的结果数组C后,需要将后边多余的0去掉,但要注意结果为0的情况

代码技巧

相减后t的处理

  • t>=0时,结果为t;当t<0时,结果为10-t(因为借了10)
  • 改写为t=(t+10)%10。用一个式子便可表示。

两个高精度数的大小比较

  • 比较两个数的位数,位数多的数一定大
  • 两个数从前往后比较,若比较的当前位不同,则结果为两者的大小结果

拓展

A B可以为正数或负数该怎么处理?

绝对值相减相加,判断字符串首字符的类型。

  • 正正:直接计算
  • 正负:转化为高精度加法
  • 负负:高精度加法,加前导-
上一篇:.NET使用Moq开源模拟库简化单元测试


下一篇:问:SQL中的通用函数及用法?