zoukankan      html  css  js  c++  java
  • 算法设计与分析:大整数乘法

    大整数乘法

    声明:本文仅个人笔记

    参考链接:
    https://www.cnblogs.com/McQueen1987/p/3348426.html
    https://blog.csdn.net/sinat_32716451/article/details/84174455

    题目和分析:

    这里面的O(n^2)就是下面的我自己画的小学乘法计算复杂度示意图

    注意:

    • T(n)代表规模为n的问题,系数4表示问题缩小到T(n/2)时,包含四次乘法(上式中AC/AD/BC/BD四次
    • 这里第一次是进行了4次的n/2的整数乘法---->4T(n/2)
    • 3次2n位的加法,2次移位----->O(n)
    • 而后来的改进主要是改进的是递归孩子乘法的次数由4变为3
    • 所以当n>1的时候主要有T(n)=4T(n/2)变成了3T(n/2)
    • 此时T(n)从O(nlog4)变成了O(nlog3),这里的log4和log3其实是以2为底的

    这里有个问题就是4次n/2乘法怎么变成n^log4的,等想好再来接着编辑吧

    代码上菜:

    注意这里的代码是十进制大整数进行相乘,而课本给出的是二进制机器数进行相乘

    XY = (A10^(n/2) + B)( C10^(n/2) + D)
    = AC10^n + AD10^(n/2) + BC10^(n/2) + BD
    = A
    C10^n + ((A-B)(D-C) + AC + BD)10(n/2) + BD
    上面的最后一行理解为“先减后加”

    而且这里代码里面是对AD+BC的另外一种形式的推导即“先加后减”

    package cn.htu.test;
    
    public class BigDataRide {
     
    	public static int sign(long a) {
     
    		return a < 0 ? -1 : 1;
     
    	}
    	
    	public static double bigdataride(long x,long y,int n) {
     
    		x = Math.abs(x);//符号交给sign函数处理,我们只处理正数
     
    		y = Math.abs(y);
     
    		if (n == 1) {
    			
    			return x * y;
     
    		}
     
    		else {
    			if (n%2==1) {
    				n = n - 1; //对奇数的操作;在课本的分析中,所做假设是n是2的幂
    			}
    			long a = x / Math.round(Math.pow( 10 , (n / 2)));//移位操作,可以理解为小数点相对左移了
     
    			long b = x - a * Math.round(Math.pow( 10 , (n / 2)));//得到的就是低位数值
     
    			long c = y / Math.round(Math.pow( 10 , (n / 2)));
     
    			long d = y - c * Math.round(Math.pow( 10 , (n / 2)));
     
    			double ac = bigdataride(a,c,n/2);//递归计算a*c
     
    			double bd = bigdataride(b,d,n/2);//计算b*d
     
    			long sum_ab = a + b;
     
    			long sum_cd = c + d;
     
    			double abcd = bigdataride(sum_ab,sum_cd,n/2);
    			//以上总共调用了3次递归函数即log3
    			
    			//原来推导式里面的((A-B)(D-C)+AC+BD)的结果其实就是先减再加,下面的是先加再减
    			//即(A+B)(C+D)-AC-BD == AD+BC
     
    			return (ac*Math.pow(10,n) + (abcd - ac - bd)*Math.pow(10,n/2) +bd);
     
    		}
     
    	}
     
    	public static void main(String[] args) {
     
    		// 十进制大整数相乘(非用户输入型)
    
    		long x = 12234L;
     
    		long y = 45243L;
     
    		String xString = String.valueOf(x);//转为字符串,计算位数存到n
     
    		int n = xString.length();
     
    		long sig = sign(x)*sign(y);//sign返回参数的正负,sig取值范围为{1,-1}
     
    		double s = bigdataride(x,y,n);//s是数值部分
     
    		System.out.println("大数相乘的计算结果为:"+s*sig);
     
     
    	}
     
    }
    
  • 相关阅读:
    JS pop push unshift shift的作用与区别
    白话js this指向问题
    JS作用域,作用域,作用链详解
    angular $q promise详解
    白话$resource,$resource中的增删改查
    ng-app与ng-app='myApp'的区别
    详解 高效字节流
    详解 字节输出流 与 字节输入流
    阶段性复习与应用——复制多级文件夹
    详解 字节流
  • 原文地址:https://www.cnblogs.com/shallow920/p/12905213.html
Copyright © 2011-2022 走看看