1.高精度加法
一般都是很大的数字相加,然后不允许使用库函数实现两个字符串或者两个链表的节点或两个数组
相加,这种问题我们一般都使用一个进位t解决,每次对应位置上数相加时都加上这个进位即可。然后这一位的值等于A+B+进位(t) % 10
,进位=进位/10
代码示例
这道题是个位数在后,我们需要从后往前加
public String addStrings(String num1, String num2) {
StringBuilder sb = new StringBuilder();
int t = 0, i = num1.length()-1, j = num2.length()-1;
//判断三个条件 只有有一个成立还继续循环 t!=0也继续循环,因为如果11+99这种,两个字符串都循环完了,但是t这时候是1,说明要补1
while(i >= 0 || j >= 0 || t != 0){
//这里进行了优化 -'0'变向的将字符转成了数组
if(i>=0) t += num1.charAt(i--)-'0';
if(j>=0) t += num2.charAt(j--)-'0';
sb.append(t % 10);
t /= 10;
}
return sb.reverse().toString();
}
如果改变一下题目,字符串表示的数是逆序的,即第一个字符是个位,第二个是十位 . . . ,我们需要从前往后加
public String addStrings(String num1, String num2) {
StringBuilder sb = new StringBuilder();
int t = 0, i = 0, j = 0;
//判断三个条件 只有有一个成立还继续循环
while(i < num1.length() || j < num2.length() || t != 0){
//这里进行了优化 -'0'变向的将字符转成了数组
if(i< num1.length()) t += num1.charAt(i--)-'0';
if(j < num2.length() t += num2.charAt(j--)-'0';
sb.append(carry%10);
carry /= 10;
}
return sb.reverse().toString();
}
链表也是类似,判断条件变为 第一个链表不为null || 第二个链表不为null || t !=0
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode dummy = new ListNode(-1);
ListNode cur = dummy;
int t = 0;
while(l1!=null || l2!=null || t!=0){
if(l1!=null){
t+= l1.val;
l1=l1.next;
}
if(l2!=null){
t+=l2.val;
l2=l2.next;
}
ListNode newNode = new ListNode(t % 10);
t /= 10;
cur.next = newNode;
cur = cur.next;
}
return dummy.next;
}
2.高精度减法
核心也是维护一个借位,从个位开始减,每次减都减去借位,当相减为负数时,将这个负数+10然后模上10
就是这一位的结果,相当是向前一位借了1 然后将借位变为1,下一次相减时减去1,
当相减为整数时,也将这个数+10模上10
,(其实还是整数本身),然后将借位变为0,那么下一次减的时候就是正常减
字符串表示的数是正序,从后往前减(从个位开始减)
这里保证m>n
如果没有此条件,需要遍历判断m和n的大小
public String cut(String m,String n){
StringBuilder sb = new StringBuilder();
int t = 0, i = m.length() - 1, j = n.length() - 1;
//这里的条件没有t!=0 减法不会多出一位数
while (i >= 0 || j >= 0) {
if (i >= 0) t = m.charAt(i--) - '0' - t;
if (j >= 0) t = t - (n.charAt(j--) - '0');
sb.append((t + 10) % 10);
if (t < 0) t = 1;
else t = 0;
}
//将结果变为正序
sb.reverse();
//去掉前导0
int k = 0;
for (k = 0; k < sb.length(); k++) {
if (sb.charAt(k) != '0') {
break;
}
}
return sb.toString().substring(k, sb.length());
}
如果字符串表示的数是倒序,就从前往后减
3.高精度乘法
也是维护一个进位,每次乘的时候加上进位,类似加法,我们将每一位直接乘这个数,不是一位一位的乘然后相加 比如给一个字符串 675 然后一个整数32 ,我们直接计算675的每一位乘32的结果
给一个字符串(高精度整数),一个整数(低精度整数),计算相乘后的结果
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String m = scanner.nextLine();
int n = scanner.nextInt();
if("0".equals(m) || n == 0){
System.out.println(0);
return;
}
StringBuilder sb = new StringBuilder();
int t = 0 , i = m.length()-1;
//因为进位可能最后不为0 需要加位数
while(i >=0 || t !=0){
//每次相乘都加上进位
if(i >= 0 ) t = n * (m.charAt(i--) - '0') + t;
sb.append(t % 10);
t /= 10;
}
System.out.println(sb.reverse().toString());
}
}
4.高精度除法
除法时从高位开始计算的,这是跟前三种不一样的地方
需要先记录余数(就是每次真正除的数),每次使用余数/n就是这一位的数,r%n就是余数
比如123除以3,第一次r=1,然后1/3等于0,那么结果的第一位就是0,然后r%n是1
然后第二轮 r=r*10+2 = 12 12/3=4,第二位就是4,然后r%n等于0
…
模拟一下列式除法即可
代码
高精度数除低精度数
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String m = scanner.nextLine();
int n = scanner.nextInt();
StringBuilder sb = new StringBuilder();
int r = 0;
int i = 0;
while (i < m.length()) {
r = r * 10 + (m.charAt(i++) - '0');
sb.append(r / n);
r = r % n;
}
//去除前导0 找到不是0的第一个位置
int k = 0;
for (k = 0; k < sb.length()-1; k++) {
if(sb.charAt(k) != '0'){
break;
}
}
System.out.println(sb.toString().substring(k,sb.length()));
System.out.println(r);
}
}