高精度运算

发布时间 2023-04-04 14:11:51作者: QING~h

高精度运算

1、高精度加法

例题:A+B Problem(高精)

传送门

题目描述:

高精度加法,相当于 a+b problem,不用考虑负数

输入格式:

分两行输入。\(a,b≤10^{500}\)

输出格式:

输出只有一行,代表 a+b 的值。

思路:

  1. 用String类型存储两个数
  2. 将两个数倒序
  3. 相加过程中用temp存储进位的值

Code:

import java.util.Arrays;
import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		String a = in.next();
		String b = in.next();
		int alen = a.length();
		int blen = b.length();
		int maxlen = Math.max(alen, blen);// 获得两个之间的较大的长度
		char[] aArray = new char[maxlen];
		char[] bArray = new char[maxlen];
		// 将两个数组的每个值都初始化为'0',否则为" "
		Arrays.fill(aArray, '0');
		Arrays.fill(bArray, '0');
		// 从个位开始加,将两个数组倒序
		for (int i = 0; i < alen; i++) {
			aArray[i] = a.charAt(alen - 1 - i);
		}
		for (int i = 0; i < blen; i++) {
			bArray[i] = b.charAt(blen - 1 - i);
		}
		int[] ans = new int[maxlen + 1];
		int temp = 0;
		for (int i = 0; i < maxlen; i++) {
			ans[i] = aArray[i] - '0' + bArray[i] - '0' + temp;
			temp = ans[i] / 10;
			ans[i] %= 10;
		}
		// 倒序输出
		if (temp != 0) {
			ans[maxlen] = temp;
			for (int i = maxlen; i >= 0; i--) {
				System.out.print(ans[i]);
			}
			return;
		} else {
			for (int i = maxlen - 1; i >= 0; i--) {
				System.out.print(ans[i]);
			}
			return;
		}
	}

}

2、高精度减法

例题:高精度减法

传送门

输入格式:

两个整数 a,b(第二个可能比第一个大)。

输出格式:

结果(是负数要输出负号)。

说明/提示

  • 20% 数据 a,b 在 long long 范围内;
  • 100% 数据$ 0<a,b≤10^{10086}$。

思路:

  1. 字符数组存储。先字符数组存储,计算长度,比较减数和被减数的大小。
  2. 将字符数组倒转存储在整数数组中
  3. 将C[0]=A[0]-B[0],如果A[0]<B[0]则向前借位。如此持续循环解决
  4. 注意最后结果C数组的最高位除零。
  5. 最后逆序输出,得到结果。

Code:

public class Main {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		String aString = in.next();
		String bString = in.next();
		int alen = aString.length();
		int blen = bString.length();
		// 如果a小于b,就交换a和b,指定a为大的那个
		// 不能直接aString.compareTo(bString)
		// ,因为compareTo函数是自左向右逐个字符比较,出现不同的字符则返回aString[i]-bString[i]的值
		if (alen < blen || (alen == blen && aString.compareTo(bString) < 0)) {
			System.out.print("-");
			String t = aString;
			aString = bString;
			bString = t;
			alen = aString.length();
			blen = bString.length();
		}
		int[] ans = new int[alen];
		int[] a = new int[alen];
		int[] b = new int[alen];

		// 反转数据
		for (int i = 0; i < alen; i++) {
			a[i] = aString.charAt(alen - 1 - i) - '0';
		}

		for (int i = 0; i < blen; i++) {
			b[i] = bString.charAt(blen - 1 - i) - '0';
		}

		for (int i = 0; i < alen; i++) {
			// 借位
			if (a[i] < b[i]) {
				a[i + 1]--;
				a[i] += 10;
			}
			ans[i] = a[i] - b[i];
		}

		boolean flag = false;
		// 可能有前导0,第一次出现非0数时进行标记,若c[i]==0&&flag则证明该0不是前导0,进行输出
		for (int i = alen - 1; i >= 0; i--) {
			if (ans[i] != 0) {
				flag = true;
				System.out.print(ans[i]);
			}
			if (ans[i] == 0 && flag)
				System.out.print(ans[i]);
		}
		// 还有一种 如果循环结束时flag==false,那么证明答案中只有0
		if (!flag) {
			System.out.print(0);
		}
	}
}

3、高精度乘法

例题:A*B Problem

题目描述:

给出两个非负整数,求它们的乘积。

输入格式:

输入共两行,每行一个非负整数。

输出格式:

输出一个非负整数表示乘积。

说明/提示

每个非负整数不超过 \(10^{2000}\)

思路:

Code:

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		String aString = in.next();
		String bString = in.next();
		if (aString.equals("0") || bString.equals("0")) {
			System.out.println(0);
			return;
		}
		int alen = aString.length();
		int blen = bString.length();
		int[] a = new int[alen];
		int[] b = new int[blen];
		int len = alen + blen;
		int[] ans = new int[len];

		for (int i = 0; i < alen; i++) {
			a[i] = aString.charAt(alen - 1 - i) - '0';
		}
		for (int i = 0; i < blen; i++) {
			b[i] = bString.charAt(blen - 1 - i) - '0';
		}

		for (int i = 0; i < alen; i++) {
			for (int j = 0; j < blen; j++) {
				ans[i + j] += a[i] * b[j];
				ans[i + j + 1] += ans[i + j] / 10;
				ans[i + j] %= 10;
			}
		}
		boolean flag = false;
		for (int i = len - 1; i >= 0; i--) {
			if (ans[i] != 0) {
				flag = true;
				System.out.print(ans[i]);
			}
			if (ans[i] == 0 && flag)
				System.out.print(ans[i]);
		}
	}
}