你会利用计算机计算10^10000^10^10000吗?(大数算法)

在利用计算机进行计算时,肯定会有一些数值的要求,那如何处理大数的加减乘除呢?我们可以利用数组的方式来计算出相应的结果。

进行高精度计算时要处理好一下几个问题:

一、数据的接收和储存

二、大数位数的确定

三、进位、借位的处理

四、商和余数的求法

下面分别来说明这几个问题:

 一、数据的接收和存储

基本思路就是小学时计算加减乘除的思路如下图所示:

将大数中的每一位取出放入数组中:

for (int i = 0; i < length1; i++) {
            a[length1-i] = str1.charAt(i)-'0';
        }

例如:123放入数组a中:

a[3] = 1  a[2] = 2  a[1] = 3

二、大数位数的确定

这个很简单,就是字符串的长度:

str.length()

 三、进位、借位处理

对于加法来说:

对于减法来说:

对于乘法来说:

具体的方式见下面的典例代码。

四、商和余数的求法

根据被除数和除数的位数进行处理。 

典例一:高精度加法:

关键算法:

 //计算大数
        int n = 1;//代表正在计算的位置  从第一位开始计算
        int x = 0;//每次的进位
        while (n<=length1||n<=length2){//代表每一位都要小于总共的位数
            c[n] = a[n] + b[n] + x;//求加数
            x = c[n]/10;//求进位
            c[n] = c[n]%10;//求此时c[n]的最终值
            n++;
        }
        //处理最高进位
        c[n] = x;
        if (c[n]==0){
            n--;
        }

完整算法(Java实现):

package ACM_BigDate;

import java.util.Scanner;

/*
高精度加法

若输入是 a b  则cin接受的形式是:next()
若输入的a
        b
        则cin接受的形式是nextLine()
 */
public class Add {
    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        String str1 = cin.nextLine();//输入大数1
        String str2 =cin.nextLine();//输入大数2
        int length1 = str1.length();//计算大数1的长度
        int length2 =str2.length();//计算大数2的长度
        int[] a = new int[100];//将大数1的每一个字符装换成数字存入a中  根据题目要求设置成相应的长度
        int[] b = new int[100];//将大数1的每一个字符装换成数字存入b中
        int[] c = new int[100];//存放结果的数组
        //例如 123 则是 a[1] = 3 a[2] = 2 a[3] = 1
        //将大数1存入a数组  但是不利用a[0]
        for (int i = 0; i < length1; i++) {
            a[length1-i] = str1.charAt(i)-'0';
        }
        //将大数2存入b数组
        for (int i = 0; i < length2; i++) {
            b[length2-i] = str2.charAt(i)-'0';
        }
        //计算大数
        int n = 1;//代表正在计算的位置  从第一位开始计算
        int x = 0;//每次的进位
        while (n<=length1||n<=length2){//代表每一位都要小于总共的位数
            c[n] = a[n] + b[n] + x;//求加数
            x = c[n]/10;//求进位
            c[n] = c[n]%10;//求此时c[n]的最终值
            n++;
        }
        //处理最高进位
        c[n] = x;
        if (c[n]==0){
            n--;
        }
        for (int i = n; i >=1 ; i--) {
            System.out.printf(String.valueOf(c[i]));
        }
    }
}

注意点:

1、根据题目要求设置数据的大小,例如大数1和大数2位数不超过1000,所以数组长度必须大于1000(这个我就错了,搞了半天,就是提交不上去,最后发现是自己搞错了需求)

2、还有就是进位的处理,一定要判断最后一个进位的处理,否则也会出错!

3、这这个例子中存储大数的数组a[0]是使用的,我觉得便于理解吧!意思就是把大数的个位放在数组的第一个位子(a[1])!!!

 典例二:高精度减法

关键算法:

int n = 1;//此时两大数需要相减的位置
        while (n <= length1 || n <= length2) {
            //如果两数相减小于0
            if (a[n] - b[n] < 0) {
                a[n] = a[n] + 10;//向高层借一位
                a[n+1]--;
            }
            c[n] = a[n] - b[n];//将两数相减的结果放入数组c中
            n++;
        }
        //最高位的0不输出
        while (c[n]==0&&n>1){
            n--;
        }

完整算法(Java实现):

package ACM_BigDate;

import java.util.Scanner;

/**
 * 大数减法  祺本质个大数加法一样  只不过主要的算法需要改变
 */
public class Jian {
    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        String str1 = cin.nextLine();
        String str2 = cin.nextLine();
        int length1 = str1.length();
        int length2 = str2.length();
        int[] a = new int[100];
        int[] b = new int[100];
        int[] c = new int[100];
        //将大数放入数组中
        for (int i = 0; i < length1; i++) {
            a[length1 - i] = str1.charAt(i) - '0';
        }
        for (int i = 0; i < length2; i++) {
            b[length2 - i] = str2.charAt(i) - '0';
        }
        int n = 1;//此时两大数需要相减的位置
        while (n <= length1 || n <= length2) {
            //如果两数相减小于0
            if (a[n] - b[n] < 0) {
                a[n] = a[n] + 10;//向高层借一位
                a[n+1]--;
            }
            c[n] = a[n] - b[n];//将两数相减的结果放入数组c中
            n++;
        }
        //最高位的0不输出
        //&&难点&& 例如: 111 - 111 结果为 000,所以要改写成0
        while (c[n]==0&&n>1){
            n--;
        }
        for (int i = n; i >=1; i--) {
            System.out.printf(String.valueOf(c[n]));
        }
    }
}

注意点:

1、大数存入数组的算法是一样的,不需要更改,还是需要注意的是数的位数。

2、注意当a[1]-b[1]时,若小于0,则需要向a[2]借一位!!

3、假设是111-110时,得出的结果时001,需要将前面的0去掉,所以采用:

 while (c[n]==0&&n>1){
            n--;
        }

4、注意a是两数中较大的数,输入时需要注意,或者需要将大小数比较之后放入对应的a、b中。

典例三:高精度乘法

如何计算大数乘法,这要回忆当年小学学的乘法最基本的法则:

关键算法:

 int n = 0;//总共的位数
        for (int i = 1; i <=length1 ; i++) {
            int x = 0;//进位
            for (int j = 1; j <=length2; j++) {
                c[i+j-1] = a[i]*b[j]+c[i+j-1]+x;//现在c = 当前a[i]与b[j]的乘积+原来的c+进位
                x = c[i+j-1]/10;//进位的计算
                c[i+j-1] = c[i+j-1]%10;
            }
            c[i+length2] = x;
        }
        n = length1+length2;//假设总共的位数时length1+length2   因为m位数乘以n位数  最大为m+n位数
        while (c[n]==0&&n>1){
            n--;
        }

完整算法(Java实现):

package ACM_BigDate;

import java.util.Scanner;

/**
 * 高精度乘法
 */
public class Chen {
    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        String str1 = cin.nextLine();
        String str2 = cin.nextLine();
        int[] a = new int[100];
        int[] b = new int[100];
        int[] c = new int[100];
        int length1 = str1.length();
        int length2 = str2.length();
        for (int i = 0; i < length1; i++) {
            a[length1-i] = str1.charAt(i) - '0';
        }
        for (int i = 0; i < length2; i++) {
            b[length2-i] = str2.charAt(i) - '0';
        }


        int n = 0;//总共的位数
        for (int i = 1; i <=length1 ; i++) {
            int x = 0;//进位
            for (int j = 1; j <=length2; j++) {
                c[i+j-1] = a[i]*b[j]+c[i+j-1]+x;//现在c = 当前a[i]与b[j]的乘积+原来的c+进位
                x = c[i+j-1]/10;//进位的计算
                c[i+j-1] = c[i+j-1]%10;
            }
            c[i+length2] = x;
        }

        n = length1+length2;//假设总共的位数时length1+length2   因为m位数乘以n位数  最大为m+n位数
        while (c[n]==0&&n>1){
            n--;
        }
        for (int i = n; i >=1 ; i--) {
            System.out.printf(String.valueOf(c[i]));
        }

    }
}

注意点:

1、大数转数组和之前一样,不必多说。

2、对于关键算法的理解,我认为最好的方式就是利用99*99,自己画图演示一遍,这样会更加理解算法

3、对于m位数乘以n位数  最大为m+n位数,我是这样理解的,假设99*99,利用放缩法,99*99<100*100,既然100*100刚好等于10000,正好是5位数,所以99*99必定小于10000,也就是必定小于5位数,最大是4位数。

4、对于a、b数组长度大小的设定,若题目中给出每个数字的长度不超过1000,则c的数组的大小一定不会超过2000,由上面的结论而退出来的。

吃完饭回来再写,有点困了。。。。。。。剩下的几个算法慢慢再写。。。。。。

典例四:高精度除法

关键算法:

完整代码:

这个算法时是所有算法中最难的那一个,有时间我在慢慢推敲。。。。。。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值