高精度加法
先看洛谷的一道高精度加法题:
public class Demo211555 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s1 = sc.next();
String s2 = sc.next();
//使用ans拼接答案
StringBuilder ans = new StringBuilder();
/**
* 这里其实我一直有一点疑问,就是这里的40%测试数据是10的18次方,这个数字的长度length
* 应该是已经大于int的数据范围了,可为啥我用int来接收 提交代码后仍然能过,
* 希望路过的大佬能指点一下,这里先感为敬。
在了解了查了一些资料以后,发现原来是我的问题,哈哈哈,是我将数字的大小和数字的长度给弄混淆了:
比如对于10^100次方,这个数字很大吧,long的最大值也就是10^18左右,可见这个数字比long的最大值大多了,可是如果用一个字符串来存储10^100是否能存下呢?答案是肯定可以的,因为:你要注意:字符串在意的不是内容,而是数量,10^100也就能占101位,101可是远远小于int的最大值啊,所以int是足够用的。
*/
int l1 = s1.length();
int l2 = s2.length();
//mod储存了进位
int mod =0;
int i=l1-1;
int j = l2-1;
//从字符串的尾部逐个相加,再进位
while(i>=0&&j>=0) {
int a = s1.charAt(i--) -'0';
int b = s2.charAt(j--) -'0';
int tmp = a+b+mod;
int k = tmp%10;
ans.append(k);
mod = tmp/10;
}
//如果两个字符串不一样长,就会剩下那个较长的,此时继续加,别忘记可能会有进位:
if(i<0) {
while(j>=0) {
int b = s2.charAt(j--) -'0';
int tmp = b+mod;
int k = tmp%10;
ans.append(k);
mod = tmp/10;
}
}else {
while(i>=0) {
int a = s1.charAt(i--)-'0';
int tmp = a+mod;
int k = tmp%10;
ans.append(k);
mod = tmp/10;
}
}
//这里是个特判,如:300+900 = 1200;
if(mod !=0) {
ans.append(mod);
}
ans.reverse();
System.out.println(ans.toString());
}
}
高精度减法
public class Demo211629 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s1 = sc.next();
String s2 = sc.next();
int len1 = s1.length();
int len2 = s2.length();
//ans用来拼接答案
StringBuilder ans = new StringBuilder();
//flag用来标记答案是否是个负数
boolean flag = false;
//时刻保持s1大于s2,因为我们习惯用大数减小数,如果有负号后期再做拼接
if(len1 == len2) {
if(s1.compareTo(s2)<0) {
String s3 = s1;
s1 = s2;
s2 = s3;
flag = true;
}
}else {
if(len1<len2) {
String s3 = s1;
s1 = s2;
s2 = s3;
flag = true;
}
}
//s1,i就对应较大的数
//s2,j就对应较小的数
int i = Math.max(len1, len2)-1;
int j = Math.min(len1, len2)-1;
int mod =0;
while(i>=0&&j>=0) {
int a = s1.charAt(i--) -'0';
int b = s2.charAt(j--) -'0';
a+=mod;
int tmp = 0;
if(a<b) {
mod = -1;
tmp = 10+a-b;
ans.append(tmp);
}else {
mod =0;
tmp = a-b;
ans.append(tmp);
}
}
//这里,好多坑的
//如果第一个数比第二个大很多如:1233333- 455
//要记得将第一个数的借位给 “借走”
while(i>=0) {
int a = s1.charAt(i--) - '0';
a+=mod;
int tmp =0;
if(a<0) {
mod = -1;
tmp = 10+a;
}else {
mod =0;
tmp = a;
}
ans.append(tmp);
}
//将前导0去掉:11- 2 = 09
int k = ans.length() -1;
while(ans.length() !=0) {
if(ans.charAt(k) == '0') {
ans.deleteCharAt(k--);
}else {
break;
}
}
//如果出现相减都是0的情况,再拼接一个0
if(ans.length() ==0) ans.append(0);
if(flag)ans.append("-");
ans.reverse();
System.out.println(ans.toString());
}
}
高精度乘法
public class Demo211728 {
static int[] c;
static int[] a;
static int[] b;
static int l1,l2,l3;
static int n = (int)1e6+10;//两个数最大长度也就是10^4000,1e6够用了。
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s1 = sc.next();
String s2 = sc.next();
a = new int[n];
b = new int[n];
c = new int[n];
//先将数据倒序存入数组:
l1 = s1.length();
l2 = s2.length();
l3 = l1+l2;
for(int i =l1 -1;i>=0;i--)a[l1-1-i] = s1.charAt(i) -'0';
for(int i =l2 -1;i>=0;i--)b[l2-1-i] = s2.charAt(i) -'0';
//处理数据:
mult(c,a,b);
//输出结果:
for(int i =l3-1;i>=0;i--) {
System.out.print(c[i]);
}
}
private static void mult(int[] c, int[] a, int[] b) {
// TODO Auto-generated method stub
for(int i = 0;i<l1;i++) {
for(int j =0;j<l2;j++) {
c[i+j]+=a[i]*b[j];
}
}
//处理进位:
for(int i =0;i<l3;i++) {
c[i+1] +=c[i]/10;
c[i]%=10;
}
//处理前导0:
while(l3 >1&&c[l3-1] ==0) l3--;
}
}
高精度除法
public class Demo211756 {
static int n = (int)(1e6+10);
static int[] c = new int[n];
static int[] a = new int[n];
static int lc;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s1 = sc.next();
long b =sc.nextLong();
int len =s1.length();
lc = len;
//现将a提取出来:
for(int i =0;i<len;i++) {
a[i] = s1.charAt(len -i -1)-'0';
}
//
div(b);
//打印结果:
for(int i =lc-1;i>=0;i--) {
System.out.print(c[i]);
}
}
private static void div(long b) {
// TODO Auto-generated method stub
//这一步真的非常巧妙,点睛之笔。
//这一步必须要将t定义成long,因为如果是9000000000/1000000000这种比较恶心的数据
//此时就会一直将t累加,如果定义成int就会越界。直到累加到大于b才行,这其实也是除数不能无限大的一个原因,因此此题将b定义小于等于10^9。
long t =0;
for(int i =lc;i>=0;i--) {
t = 10*t+a[i];
c[i] = (int)(t/b);
t = (int)(t%b);
}
//删掉前导0
while(lc>1&&c[lc-1] ==0) lc--;
}
}
java自带高精度运算
唯一的一点感想就是:写完了这些题目以后,发现java原来自带高精度BigInteger,要哭死了。
下面是java高精度写法:
import java.util.*;
import java.math.*;
public class Demo231542 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
BigInteger a = sc.nextBigInteger();
BigInteger b = sc.nextBigInteger();
System.out.println(a.add(b));
}
}
import java.util.*;
import java.math.*;
public class Demo231544 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
BigInteger a = sc.nextBigInteger();
BigInteger b = sc.nextBigInteger();
System.out.println(a.subtract(b));
}
}
import java.util.*;
import java.math.*;
public class Demo231548 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
BigInteger a = sc.nextBigInteger();
BigInteger b = sc.nextBigInteger();
System.out.println(a.multiply(b));
}
}
import java.util.*;
import java.math.*;
public class Demo231549 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
BigInteger a = sc.nextBigInteger();
if(a.equals(new BigInteger("0"))) {
System.out.print(0);
return ;
}
BigInteger b = sc.nextBigInteger();
System.out.println(a.divide(b));
}
}