Java-高精度计算

前言

整数的四则运算,在编程中是非常常见的。在Java中也是如此,在Java的整形数据类型中较为常用且能存储数值较大的,也只有 int、 long 这两个数据类型,这两个能存储数值的大小范围分别是,int : -2的31次方 ~ +2的31次方减一,long:-2的63次方 ~ +2的63次方减一。

这样的存储范围在日常的计算是肯定够用的了,但是如果需要计算很大的数据范围,直接超出这两个类型所能存储的最大值,那么数据也是会溢出的。

不过Java有专门用于大数计算的API,如BigInteger类等,不过如何实现大数的四则运算,这种思想是可以学习的。



1、大正整数加法


给定两个正整数(不含前导 0),计算它们的和。

数据范围:1 ≤ 整数长度 ≤ 10⁵;

计算方式:
Java-高精度计算_第1张图片


Code

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 lenA=a.length();
        int lenB=b.length();
        
        StringBuilder sb=new StringBuilder("");
        
        int sum=0;
        int i=lenA-1,j=lenB-1;
        
        // 从最低位开始加
        while(i >= 0 || j >= 0){
            // 末尾取
            int numa=(i == -1) ? 0 : a.charAt(i--)-0x30;
            int numb=(j == -1) ? 0 : b.charAt(j--)-0x30;
            sum+=(numa+numb);

            sb.append(sum%10);
            
            sum/=10;
        }
        // 表示还需进一位
        if(sum != 0){
            sb.append(1);
        }
        System.out.println(sb.reverse().toString());
    }
}


2、大正整数减法


给定两个正整数(不含前导 0),计算它们的差,计算结果可能为负数。

数据范围: 1 ≤ 整数长度 ≤ 10⁵;

计算方式:
Java-高精度计算_第2张图片


Code

import java.util.Scanner;
import java.math.BigInteger;

public class Main{
    
    public static boolean cmp(int[] a,int[] b){
        
        if(a.length != b.length) { return a.length > b.length;  }
        
        for(int i=a.length-1; i >= 0; --i){
            if(a[i] != b[i]) { return a[i] > b[i]; }
        }
        return true;
    }
    
    public static String sub(int[] a,int[] b){
        
        StringBuilder sb=new StringBuilder("");
        
        for(int i=0,t=0; i<a.length; ++i){
            // t=a[i]-b[i]-t;
            t=a[i]-t;
            if(i < b.length) { t-=b[i]; }
            // a[i]-b[i] >= 0 ,那么+10%10互相抵消
            // < 0 ,那么相等于a[i]-b[i]+10,+10等于借位,再%10
            sb.append((t+10)%10);
            // 借位判断
            if(t < 0) { t=1; }
            else { t=0; } 
        }
        
        // 去除前导0
        String s=sb.reverse().toString();
        int i=0;
        for(int end=s.length()-1; i<end; ++i){
            if(s.charAt(i) != '0') break;
        }
        return s.substring(i,s.length());
    }
    
    public static void main(String[] args){
        Scanner in=new Scanner(System.in);
        
        String a=in.next(); // 3 2
        String b=in.next(); // 1 1
        
        int[] arrA=new int[a.length()];
        int[] arrB=new int[b.length()];
        
        for(int i=arrA.length-1; i>=0; --i)
            { arrA[arrA.length-1-i]=a.charAt(i)-0x30; }
        for(int i=arrB.length-1; i>=0; --i)
            { arrB[arrB.length-1-i]=b.charAt(i)-0x30; }
        
        // 使用保证计算时 a > b
        if(cmp(arrA,arrB) ){
            System.out.print(sub(arrA,arrB));
        }else{
            System.out.print("-"+sub(arrB,arrA));
        }
        
    }
}


3、大正整数乘法

给定两个非负整数(不含前导 0) A 和 B,请你计算 A×B的值。

数据范围: 1 ≤ A的长度 ≤ 10⁵,0 ≤ B ≤ 10000
计算方式:
Java-高精度计算_第3张图片


Code

import java.util.Scanner;

public class Main{
    
    public static String process(int[] nums,int b){
        StringBuilder sb=new StringBuilder();
        
        int t=0;
        for(int i=0; i<nums.length || t != 0; ++i){
            // int num=nums[i]*b+t;
            // sb.append(num%10);
            // t+=num/10;
            if(i < nums.length) t+=nums[i]*b;
            sb.append(t%10);
            t/=10;
        }
        
        return sb.reverse().toString();
    }
    
    public static void main(String[] args){
        Scanner in=new Scanner(System.in);
        
        String numA=in.next();
        int numB=in.nextInt();
        
        if(0 == numB) {
            System.out.print(0);
            return;
        }
        
        int[] nums=new int[numA.length()];
        for(int i=nums.length-1,j=0; i>=0; --i,++j){
            nums[j]=numA.charAt(i)-0x30;
        }
        
        System.out.print(process(nums,numB));
    }
}


4、大正整数除法

给定两个非负整数(不含前导 0) A,B,请你计算 A/B的商和余数。

数据范围: 1 ≤ A的长度 ≤ 10⁵ , 1 ≤ B ≤ 10000 , B 一定不为 0

计算方式:
Java-高精度计算_第4张图片


Code

import java.util.Scanner;

public class Main{
    
    static int r;
    // r是余数
    public static String div(int[] nums,int b){
        StringBuilder sb=new StringBuilder();
        r=0;
        // 从高位往地位走
        for(int i=nums.length-1; i >= 0; --i){
            r=r*10+nums[i];	// 将剩下的数取下来
            sb.append(r/b);	// 计算商
            r%=b;	// 计算余数
        }
        
        // 去除前导零
        int i=0;
        int len=sb.length();
        while(i < len && sb.charAt(i) == '0'){
            ++i;
        }
        
        if(i == len) { return "0"; }
        
        return sb.substring(i);
    }
    
    public static void main(String[] args){
        Scanner in=new Scanner(System.in);
        
        String numA=in.next();
        int numB=in.nextInt();
        
        if(0 == numB) {
            System.out.print(0);
            return;
        }
        
        int[] nums=new int[numA.length()];
        for(int i=nums.length-1,j=0; i>=0; --i,++j){
            nums[j]=numA.charAt(i)-0x30;
        }
        
        System.out.println(div(nums,numB));
        System.out.println(r);
    }
}

End

你可能感兴趣的:(java,开发语言,算法)