蓝桥杯算法训练P0805 大数乘法

一、题目

“蓝桥杯”练习系统 (lanqiao.cn)

当两个比较大的整数相乘时,可能会出现数据溢出的情形。为避免溢出,可以采用字符串的方法来实现两个大数之间的乘法。具体来说,首先以字符串的形式输入两个整数,每个整数的长度不会超过10位,然后把它们相乘的结果存储在另一个字符串当中(长度不会超过20位),最后把这个字符串打印出来。例如,假设用户输入为:62773417和12345678,则输出结果为:774980393241726.
  编写函数 void Multiply(char* s1, char* s2, char* result); 实现大数乘法(只考虑正整数),其中result = s1 * s2.
  编写main函数测试该函数的正确性.

输入:
  62773417 12345678

输出:
  774980393241726

二、思路

以10000为base进行大数拆分

将大数拆分成小部分

根据乘法列竖式的原理

将结果的小部分相加(进位)

得出结果分成四个部分放在一维数组中

最后将一维数组顺序输出

得到的结果即为乘法的结果

三、代码实现

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        long a = sc.nextLong();
        long b = sc.nextLong();
        int i = 0;
        long[] temp = bigMult(a,b);
        while(i < 4){
           System.out.print(temp[i]);
           i++;
        }


    }


    static long[] bigMult(long a,long b){
       long[] r = {0,0,0,0};
       long base = 10000;

       long x1 = a % base;//得到数字a万位以下的数位
       long x2 = a / base;//得到数字a整万数
       long y1 = b % base;//同理分解b
       long y2 = b / base;

       long n1 = x1 * y1;//将两个数字万位以下的数字相乘得到乘法竖式第一行
       long n2 = x1 * y2;//交叉相乘 得到乘法竖式中间两行
       long n3 = x2 * y1;
       long n4 = x2 * y2;//万位以上数字相乘得到乘法竖式最后一行

       r[3] = n1 % base;//第一行的万位以下数字作为数组最后一位 作为最终结果的后面部分
       r[2] = n1 / base + n2 % base + n3 % base;//最终结果的倒数第二部分 为乘法竖式第一行前部分加上乘法竖式二 三行后部分
       r[1] = n2 / base + n3 / base + n4 % base;//最终结果的第二部分为乘法竖式第二三行前部分加上第四行后部分
       r[0] = n4 / base;//最后最终结果的第一部分为乘法竖式第三行前部分

       r[1] += r[2] / base;//此时只有第四部分和第三部分进行了进位操作 还剩下第一第二第三部分还未进行进位操作 最后将这三位相互之间进行进位操作
       r[2] = r[2] % base;
       r[0] += r[1] / base;
       r[1] = r[1] % base;

       return r;


    }
}

四、出现问题

以上代码好理解 但是这里并未排除两个相乘的大数过小的情况 也就是最终结果的数组前面为零的情况 导致最终输出结果出错 

例如:

输入:358173862983 1
输出:0358173862983

很明显是不合理的

五、问题解决

所以改进最后主函数中代码

import java.util.Scanner;

public class Main{
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        long a = sc.nextLong();
        long b = sc.nextLong();
        int i = 0;
        long[] temp = bigMult(a,b);
        //从第一个不为零的位置开始输出
        for(long n :temp){
            if(n != 0){
                for(int j = i;j < 4;j++)
                    System.out.print(temp[j]);
                break;
            }else{
                i++;
            }
        }
      

    }


    static long[] bigMult(long a,long b){
       long[] r = {0,0,0,0};
       long base = 10000;
       long x1 = a % base;
       long x2 = a / base;
       long y1 = b % base;
       long y2 = b / base;

       long n1 = x1 * y1;
       long n2 = x1 * y2;
       long n3 = x2 * y1;
       long n4 = x2 * y2;

       r[3] = n1 % base;
       r[2] = n1 / base + n2 % base + n3 % base;
       r[1] = n2 / base + n3 / base + n4 % base;
       r[0] = n4 / base;

       r[1] += r[2] / base;
       r[2] = r[2] % base;
       r[0] += r[1] / base;
       r[1] = r[1] % base;

       return r;


    }
}

六、完结撒花

通过啦

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值