大整数乘法实现思路

1、大整数乘法的实现思路(一):模拟手工列竖式计算两个大整数的乘积

  • 模拟手工计算两个整数相乘的过程:逐位相乘,错位累加,最后进位。以 1235789×6452351 1235789 × 6452351 为例:

    • 相乘的前提: 被乘数位数 >= 乘数位数。 x×y x × y 的逐位相乘次数取决于乘数y的位数。
      • 低位补0:乘数y从十位数开始乘以被乘数的每位时,相乘后的结果的低位要补足相应0的数目,例如:从十位开始,则需要补个位的0;从百位开始,则需要补十位和个位的0,诸如此类。
      • 高位补0:m位的被乘数x和n位的乘数y相乘,最终累加和的位数为:m+n-1,所以相乘后的结果的高位也要补足相应的0的数目,例如:乘数6452351的十位乘以被乘数1235789的每位时,算上低位补的0,数组中一共是8位,所以乘积结果需要在高位补0:(7+7-1)-8=5个。
    • 乘数的每位和被乘数的每位逐位相乘,每次相乘结果如下:

      10的幂  [0, 1, 2, 3,   4, 5,  6,  7, 8, 9,10,11,12]
      第一次: [9, 8, 7, 5,   3, 2,  1,  0, 0, 0, 0, 0,0]
      第二次: [0,45,40,35,  25,15, 10,  5, 0, 0, 0, 0,0]
      第三次: [0, 0,27,24,  21,15,  9,  6, 3, 0, 0, 0,0]
      第四次: [0, 0, 0,18,  16,14, 10,  6, 4, 2, 0, 0,0]
      第五次: [0, 0, 0, 0,  45,40, 35, 25,15,10, 5, 0,0]
      第六次: [0, 0, 0, 0,   0,36, 32, 28,20,12, 8, 4,0]
      第七次: [0, 0, 0, 0,   0, 0, 54, 48,42,30,18,12,6]
      逐位累加:[9,53,74,82,110,122,151,118,84,54,31,16,6]
    • 进位:除了最高位,每位逢十进一,本位只留一个数字。
      [9,53,74,82,110,122,151,118,84,54,31,16,6]进位结果:[9, 3, 9, 9, 8, 3, 4, 4, 7, 3, 7, 9, 7]

  • 上述大整数相乘思路的代码实现(java):
package com.nwnu.algorithm.divide_and_conquer.bigInteger_multiply;

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

/**
 * @Author gaoyF
 * @Date 2018/7/3 9:28
 * @Description  任意大整数相乘
 */
public class BigIntegerMultiply {
    public static void main(String[] args) {

        System.out.print("被乘数:");
        Scanner sc_a = new Scanner(System.in);
        String x_a = sc_a.nextLine();

        System.out.print("乘数:");
        Scanner sc_b = new Scanner(System.in);
        String x_b = sc_b.nextLine();

        //调用multiply()方法计算两个大整数的乘积
        String result = multiply_v1(x_a,x_b);
        System.out.printf("multiply    乘积:%s",result);
        System.out.println('\r');

        //计算结果正误验证
        BigInteger bi_x_a = new BigInteger(x_a);
        BigInteger bi_x_b = new BigInteger(x_b);
        System.out.printf("bigInteger  乘积:%s",bi_x_a.multiply(bi_x_b));
    }

    /**
     * 模拟手工计算大整数相乘的过程:逐位相乘,然后再进位
     * @param x_a   被乘数
     * @param x_b   乘数
     * @return
     */
    public static String multiply_v1(String x_a,String x_b) {
        /**
         * 始终保证被乘数的位数大于乘数的位数
         */
        if (x_a.length() < x_b.length()) {
            String x_t = x_a;
            x_a = x_b;
            x_b = x_t;
        }
        /**
         * 将字符串形式的被乘数和乘数解析至列表al_a/al_b,并倒序存储
         */
        ArrayList<Character> al_a = new ArrayList<>();
        ArrayList<Character> al_b = new ArrayList<>();
        ArrayList<Integer> al_z = new ArrayList<>(); //al_z用来存储被乘数和乘数各位乘积的累加和
        for (int i = 0; i < x_a.length() + x_b.length()-1; i++) {
            al_z.add(0);
        }
        for (int i = x_a.length()-1; i >= 0 ; i--) {
            al_a.add(x_a.charAt(i));
        }
        for (int i = x_b.length()-1; i >= 0 ; i--) {
            al_b.add(x_b.charAt(i));
        }
//        System.out.println(al_a);
//        System.out.println(al_b);
        /**
         * 被乘数和乘数累积和计算
         */
        for (int i = 0; i < al_b.size(); i++) {
            ArrayList<Integer> al_y = new ArrayList<>(); //al_y用于存储每次累乘完后的结果
            //低位补0
            if (i != 0) {
                for (int k = 0; k < i; k++) {
                    al_y.add(0);
                }
            }
            for (int j = 0; j < al_a.size(); j++) {
                //ASCII码值相减,获得字符数字表示的整型数字
                al_y.add(((int)al_a.get(j).charValue()-(int)('0')) * ((int)al_b.get(i).charValue()-(int)('0')));
            }
            //高位补0
            if (al_y.size() != al_z.size()) {
                for (int k = al_y.size(); k < al_z.size(); k++) {
                    al_y.add(0);
                }
            }
//            System.out.println(al_y);
            //累加和
            for (int k = 0; k < al_y.size(); k++) {
                al_z.set(k,al_y.get(k) + al_z.get(k));
            }
        }
//        System.out.println(al_z);
        /**
         * 进位处理
         */
        for (int i = 0; i < al_z.size()-1; i++) {
            if (al_z.get(i) >= 10) {
                al_z.set(i+1,al_z.get(i+1) + al_z.get(i)/10);
                al_z.set(i,al_z.get(i)%10);
            }
        }
//        System.out.println(al_z);
        /**
         * 返回乘积结果
         */
        String value = "";
        for (int i = al_z.size()-1; i >= 0 ; i--) {
            value = value.concat(al_z.get(i).toString());
//            System.out.println(value);
        }
        return value;
    }
}
  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值