分治算法之大整数相乘问题

1.问题描述

求两个大数A、B乘积的准确结果

其中A和B均为100位以上的十进制整数

A和B的位数可以不相等


2.问题分析

(1)

100位以上的整数,用整数变量直接存储装不下

所以,中间运算时,牵扯到大数肯定当做字符串来存储

(2)

A和B直接乘操作肯定是操作不了,必须是分开来处理

可以二分法,将AB转换

A=A1*10^(n1/2) +A0 ----- n1为a的位数

B=B1*10^(n2/2)+B0 -----n2为b的位数

那么 AB={A110(n1/2)+A0}*{B1*10(n2/2)+B0}

化简得

 A*B= 
(A1*B1)*10^[(n1+n2)/2] 
+(A1*B0)*10^(n1/2) 
+(A0*B1)*10^(n2/2) 
+(A0*B0)

那么就把 n1 位的整数与 n2位的整数相乘的问题转化为

1.四个`n1/2`位的整数和`n2/2`位的整数相乘

2.三次移位

3.四次“大数”加法

3.问题解决

(1)n1/2位的整数和n2/2位的大整数相乘

问题又回到了原点——大整数相乘问题

问题的解决需要调用自身来解决——递归

(2)移位

移位相当于是在后边补0

那么就在要移位的数(字符串)后面添加一定量的0即可

(3)“大数”加法

因为中间操作的都是比较大的数,因此即使是中间值的相加,也是比较大的数,故要采用大数相加

大数相加 问题 参见 大数相加


4.代码实现

import java.math.BigInteger;
import java.util.Scanner;
import org.stone.stack.MyBigAdd;
/**
 * @ClassName_MyBigIntegerMutiply
 * @author_Stone6762
 * @CreationTime_2016年10月22日 下午3:39:57
 * @Description_ 大整数乘法A x B    AB可以为不同的位数 
 * 采用的是: 分治的思想,二分 
 */
public class MyBigIntegerMutiply1 {

    /**
     * @Description:未优化的大数相乘
     * @param a
     * @param b
     * @return a*b={a1*10^(n1/2)+a0}*{b1*10^(n2/2)+b0} 
     */
    public static String Mutiply1(String a, String b)// 用字符串读入2个大整数
    {
        String result = "";
        if (a.length() == 1 || b.length() == 1)// 递归结束的条件
                       //其中一个长度为1,另一个不一定
            result = "" + Long.valueOf(a) * Long.valueOf(b);
        else// 如果2个字符串的长度都 >= 2
        {
            //1.分割成  a1  a0  b1  b0
            int lengthA0 = a.length() / 2;
            int lengthA1=a.length()-lengthA0;
            String a1 = a.substring(0, lengthA1); // 截取前一半的字符串(较短的一半)
            String a0 = a.substring(lengthA1, a.length()); // 截取后一半的字符串
            
            int lengthB0 = b.length() / 2;
            int lengthB1=b.length()-lengthB0;
            String b1 = b.substring(0, lengthB1);
            String b0 = b.substring(lengthB1, b.length());
            // * a*b=
            // * (a1*b1)* 10^[(n1+n2)/2 ]
            // * +(a1*b0)*10^(n1/2)
            // * +(a0*b1)*10^(n2/2)
            // * +(a0*b0)
            //2.计算展开式中的乘法
            String a1b1 = Mutiply1(a1, b1);
            String a1b0 = Mutiply1(a1, b0);
            String a0b1 = Mutiply1(a0, b1);
            String a0b0 = Mutiply1(a0, b0);

            //3.模拟移位
            String resulta1b1 = a1b1;
            for (int i = 0; i < lengthA0+lengthB0; i++) {
                resulta1b1 += "0";
            }
            String resulta1b0 = a1b0;
            for (int i = 0; i <lengthA0; i++) {
                resulta1b0 += "0";
            }
            String resulta0b1 = a0b1;
            for (int i = 0; i < lengthB0; i++) {
                resulta0b1 += "0";
            }   
            //4.大数相加
            result = MyBigAdd.add(resulta1b1, resulta1b0);
            result = MyBigAdd.add(result, resulta0b1);
            result = MyBigAdd.add(result, a0b0);
        }
        return result;
    }
    
    /** 
     * @Description拿BigInteger自身大数相乘来判断自身算法的正确与否
     * @param args
     */
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        while (scan.hasNext()) {
            
            String aString=scan.next();
            String bString=scan.next();
            
            BigInteger aBigInteger=new BigInteger(aString);
            BigInteger bBigInteger=new BigInteger(bString);
            
            String reslut1=aBigInteger.multiply(bBigInteger).toString();
            String result2=Mutiply1(aString, bString);
            
            System.out.println("标准答案:  "+reslut1);
            System.out.println("计算结果:  "+result2);
            
            System.out.println("结果是否正确:  "+reslut1.equals(result2));
        }
        
    }
}

5.缺点

1. A和B的位数可以不相同

但是相差不能太大,不能超过long的范围

2.时间复杂度和空间复杂度比较高,没有优化

6.更简单大数相乘大数相加

java 类库自带 BigInteger和BigDecimal可以处理大整数和大浮点数
其中有处理相加和相乘的函数


如果仅仅是为了处理大数的相加和相乘,而不是为了研究,可以直接调用其封装好的函数即可


(1)调用java类库的大数相加

public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        while (scan.hasNext()) {    
            String aString=scan.next();
            String bString=scan.next();
            BigInteger aBigInteger=new BigInteger(aString);
            BigInteger bBigInteger=new BigInteger(bString);
            String resultString=aBigInteger.add(bBigInteger).toString();    
            System.out.println("a加上b等于 "+resultString);
        }
    }

(2)调用java类库的大数相乘

public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        while (scan.hasNext()) {    
            String aString=scan.next();
            String bString=scan.next();
            BigInteger aBigInteger=new BigInteger(aString);
            BigInteger bBigInteger=new BigInteger(bString);
            String reslut1=aBigInteger.multiply(bBigInteger).toString();    
            System.out.println("a乘以b等于 "+reslut1);
        }
    }

欢迎一起讨论大数相乘的优化问题


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容