java大数乘法分治_分治法的经典问题——大整数相乘

分治法的经典问题——大整数相乘

分治法的原理

分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同。求出子问题的解,就可得到原问题的解。即一种分目标完成程序算法,简单问题可用二分法完成。(来自度娘的搬运工)

简单的说,分治就是分而治之,把一个问题拆分成几个小问题,最后再汇总解决的办法。

有两点需要记住:

(1) 分治法基本思想是将一个规模为n的问题分解为k个规模较小的子问题,这些子问题相互独立且与原问题相同。

(2)递归的解这些子问题,然后将各子问题的解合并得到原问题的解。

分治法的重点是分析问题是否可以划分为规模较小的子问题,难点是如何划分以及划分之后如何将各个子问题的解合并成最终的解。这一般需要用到数学知识或者其他理论。

下面我们用图来说明:

ec3e2b6a1bbec0f874ea5abcc8944db2.png

通过大整数相乘问题来了解分治法(理想状态下)

这里我们假设有两个大整数X、Y,分别设X=1234、Y=5678。现在要求X*Y的乘积,小学的算法就是把X与Y中的每一项去乘,但是这样的乘法所需的时间复杂度为,效率比较低下。那我们可以采用分治的算法,将X、Y分别拆分为A与B、C与D,如下图:

ecb1843d78510e05e6c321cd31d08562.png

31f867493bed3966a413b0b32d41a7ac.png

注:我们这里取的大整数X、Y是在理想状态下,即X与Y的位数一致,且

f68dc82c8a2c000eccdf2c03bcfe3d49.png

算法分析

首先将X和Y分成A,B,C,D

此时将X和Y的乘积转化为(1)式,把问题转化为求解因式分解的值

在(1)式中,我们一共需要进行4次n/2的乘法(AC2次,AD、BC各一次)和3次加法,因而该算法的时间复杂度为:

d433680cc89c4e8ecae09fe522e90fc4.png

通过master定理可以求得

7397857dc03e9b9b4d92f4d8b7179c52.png,跟小学算法的时间复杂度没有区别。

但是我们再来看看,我们是否可以用加法来换取乘法?因为多一个加法操作,也是常数项,对时间复杂度没有影响,如果减少一个乘法则不同。

(1)式化为:

f6b2b5ebe829e2ca00df763ffdc60b8c.png (2)

现在的时间复杂度为:

cc8e41c655feeb54ac1d9913e9a25d48.png,通过master定理求得,

149dc8b6e6dee4762422c532dac2acf9.png

理想状态下代码实现(部分):

c#:

static void Main(string[] args)

{

//SameNumber();

//UnSameNumber();

UnSameNumber2();

}

static int SIGN(long A)

{

return A > 0 ? 1 : -1;

}

#region 两整数位数相同

private static void SameNumber()

{

Console.Write("请输入两个大整数:\nX=");

long X = Convert.ToInt64(Console.ReadLine());

Console.Write("Y=");

long Y = Convert.ToInt64(Console.ReadLine());

Console.Write("请输入两个大整数的长度:n=");

int n = Convert.ToInt32(Console.ReadLine());

long sum = CalculateSame(X, Y, n);

Console.WriteLine("普通乘法 X*Y={0}*{1}={2}\n", X, Y, X * Y);

Console.WriteLine("分治乘法 X*Y={0}*{1}={2}\n", X, Y, sum);

}

static long CalculateSame(long X, long Y, int n)

{

int sign = SIGN(X) * SIGN(Y);

X = Math.Abs(X);

Y = Math.Abs(Y);

if (X == 0 || Y == 0)

return 0;

else if (n == 1)

return sign * X * Y;

else

{

long A = (long)(X / Math.Pow(10, n / 2));

long B = (long)(X % Math.Pow(10, n / 2));

long C = (long)(Y / Math.Pow(10, n / 2));

long D = (long)(Y % Math.Pow(10, n / 2));

long AC = CalculateSame(A, C, n / 2);

long BD = CalculateSame(B, D, n / 2);

long ABCD = CalculateSame((A - B), (D - C), n / 2) + AC + BD;

//Console.WriteLine("A={0} B={1} C={2} D={3}\n", A, B, C, D);

return (long)(sign * (AC * Math.Pow(10, n) + ABCD * Math.Pow(10, n / 2) + BD));

}

}

#endregion

75cf1238d6adf8b9a8c99834ec629573.png

大整数相乘算法非理想状态下

这里我们还是假设有两个大整数X、Y,分别设X=123、Y=45678。现在要求X*Y的乘积,乘法所需的时间复杂度为。我们采用分治的算法,将X、Y分别拆分为A与B、C与D,如下图:

dac84a15d0919b169250be4e80e81ce1.png

aa2b783c8a41ddf4da369899fc64c11f.png   (3)

在(3)式中,我们一共需要进行2次xn0的乘法(AC、AD各一次)、2次yn0的乘法(AC、BC各一次)和3次加法,因而该算法的时间复杂度为:

e16134fd4e64689f655df766217c015e.png

现在我们用加法来换取乘法并计算其时间复杂度。

(3)式化为:

d4ee497bf75a0fff61a6350dc2bde9d2.png(4)

现在的时间复杂度为:

8fb844e4098cd112aed2a20fd70adb2b.png

由于

27496840210e038aba71368790265787.png,所以(4)式的时间复杂度小于(3)式的时间复杂度。

非理想状态下代码实现(部分):

c#:

#region 两整数位数不相同

private static void UnSameNumber2()

{

Console.Write("请输入两个大整数:\nX=");

long X = Convert.ToInt64(Console.ReadLine());

Console.Write("Y=");

long Y = Convert.ToInt64(Console.ReadLine());

Console.Write("请输入X的长度:xn=");

int xn = Convert.ToInt32(Console.ReadLine());

Console.Write("请输入Y的长度:yn=");

int yn = Convert.ToInt32(Console.ReadLine());

long sum = CalculateUnSame2(X, Y, xn, yn);

Console.WriteLine("\n普通乘法 X*Y={0}*{1}={2}", X, Y, X * Y);

Console.WriteLine("分治乘法 X*Y={0}*{1}={2}\n", X, Y, sum);

}

static long CalculateUnSame2(long X, long Y, int xn, int yn)

{

if (X == 0 || Y == 0)

return 0;

else if ((xn == 1 && yn == 1) || xn == 1 || yn == 1)

return X * Y;

else

{

int xn0 = xn / 2, yn0 = yn / 2;

int xn1 = xn - xn0, yn1 = yn - yn0;

long A = (long)(X / Math.Pow(10, xn0));

long B = (long)(X % Math.Pow(10, xn0));

long C = (long)(Y / Math.Pow(10, yn0));

long D = (long)(Y % Math.Pow(10, yn0));

//Console.WriteLine("A={0}*10^{1} B={2}*10^{3} C={4}*10^{5} D={6}*10^{7}\n", A, xn1, B, xn0, C, yn1, D, yn0);

long AC = CalculateUnSame2(A, C, xn1, yn1);

long BD = CalculateUnSame2(B, D, xn0, yn0);

long ABCD = CalculateUnSame2((long)(A * Math.Pow(10, xn0) - B), (long)(D - C * Math.Pow(10, yn0)), xn1, yn1);

return (long)(2 * AC * Math.Pow(10, (xn0 + yn0)) + ABCD + 2 * BD);

}

}

#endregion

36a61e1ac36cc8f7b1e17fcc0195fe98.png

理想状态下与非理想状态下代码实现(完整):

c语言:

#include

#include

#include

void SameNumber();

void UnSameNumber();

int SIGN(long A);

long CalculateSame(long X, long Y, int n);

long CalculateUnSame(long X, long Y, int xn, int yn);

int main()

{

SameNumber();

UnSameNumber();

return (0);

}

int SIGN(long A)

{

return A > 0 ? 1 : -1;

}

void SameNumber()

{

long X=0,Y = 0;

int n=0;

printf("理想状态下用法!");

printf("请输入两个大整数:\nX=");

scanf("%d",&X);

printf("Y=");

scanf("%d",&Y);

printf("请输入两个大整数的长度:n=");

scanf("%d",&n);

long sum = CalculateSame(X, Y, n);

printf("普通乘法 X*Y=%d*%d=%d\n",X,Y,X*Y);

printf("分治乘法 X*Y=%d*%d=%d\n",X,Y,sum);

}

long CalculateSame(long X, long Y, int n)

{

int sign = SIGN(X) * SIGN(Y);

X = labs(X);

Y = labs(Y);

if (X == 0 || Y == 0)

return 0;

else if (n == 1)

return sign * X * Y;

else

{

long A = (long)(X / pow(10, n / 2));

long B = (X % (long)pow(10, n / 2));

long C = (long)(Y / pow(10, n / 2));

long D = (Y % (long)pow(10, n / 2));

long AC = CalculateSame(A, C, n / 2);

long BD = CalculateSame(B, D, n / 2);

long ABCD = CalculateSame((A - B), (D - C), n / 2) + AC + BD;

//cout<

return (long)(sign * (AC * pow(10, n) + ABCD * pow(10, n / 2) + BD));

}

}

void UnSameNumber()

{

long X=0,Y = 0;

int xn=0,yn=0;

printf("非理想状态下用法!");

printf("请输入两个大整数:\nX=");

scanf("%d",&X);

printf("Y=");

scanf("%d",&Y);

printf("请输入X的长度:xn=");

scanf("%d",&xn);

printf("请输入Y的长度:xn=");

scanf("%d",&yn);

long sum = CalculateUnSame(X, Y, xn,yn);

printf("普通乘法 X*Y=%d*%d=%d\n",X,Y,X*Y);

printf("分治乘法 X*Y=%d*%d=%d\n",X,Y,sum);

}

long CalculateUnSame(long X, long Y, int xn, int yn)

{

if (X == 0 || Y == 0)

return 0;

else if ((xn == 1 && yn == 1) || xn == 1 || yn == 1)

return X * Y;

else

{

int xn0 = xn / 2, yn0 = yn / 2;

int xn1 = xn - xn0, yn1 = yn - yn0;

long A = (long)(X / pow(10, xn0));

long B = (long)(X % (long)pow(10, xn0));

long C = (long)(Y / pow(10, yn0));

long D = (long)(Y % (long)pow(10, yn0));

long AC = CalculateUnSame(A, C, xn1, yn1);

long BD = CalculateUnSame(B, D, xn0, yn0);

long ABCD = CalculateUnSame((long)(A * pow(10, xn0) - B), (long)(D - C * pow(10, yn0)), xn1, yn1);

return (long)(2 * AC * pow(10, (xn0 + yn0)) + ABCD + 2 * BD);

}

}

c++语言:

#include

#include

#include

int count=0;

using namespace std;

void SameNumber();

void UnSameNumber();

int SIGN(long A);

long CalculateSame(long X, long Y, int n);

long CalculateUnSame(long X, long Y, int xn, int yn);

int main()

{

SameNumber();

UnSameNumber();

return (0);

}

int SIGN(long A)

{

return A > 0 ? 1 : -1;

}

void SameNumber()

{

cout<

cout<

long X = 0;

cin>>X;

cout<

long Y = 0;

cin>>Y;

cout<

int n = 0;

cin>>n;

long sum = CalculateSame(X, Y, n);

cout<

cout<

}

long CalculateSame(long X, long Y, int n)

{

int sign = SIGN(X) * SIGN(Y);

X = abs(X);

Y = abs(Y);

if (X == 0 || Y == 0)

return 0;

else if (n == 1)

return sign * X * Y;

else

{

long A = (long)(X / pow(10, n / 2));

long B = (X % (long)pow(10, n / 2));

long C = (long)(Y / pow(10, n / 2));

long D = (Y % (long)pow(10, n / 2));

long AC = CalculateSame(A, C, n / 2);

long BD = CalculateSame(B, D, n / 2);

long ABCD = CalculateSame((A - B), (D - C), n / 2) + AC + BD;

cout<

return (long)(sign * (AC * pow(10, n) + ABCD * pow(10, n / 2) + BD));

}

}

void UnSameNumber()

{

cout<

cout<

long X = 0;

cin>>X;

cout<

long Y = 0;

cin>>Y;

cout<

int xn = 0;

cin>>xn;

cout<

int yn = 0;

cin>>yn;

long sum = CalculateUnSame(X, Y, xn,yn);

cout<

cout<

}

long CalculateUnSame(long X, long Y, int xn, int yn)

{

if (X == 0 || Y == 0)

return 0;

else if ((xn == 1 && yn == 1) || xn == 1 || yn == 1)

return X * Y;

else

{

int xn0 = xn / 2, yn0 = yn / 2;

int xn1 = xn - xn0, yn1 = yn - yn0;

long A = (long)(X / pow(10, xn0));

long B = (long)(X % (long)pow(10, xn0));

long C = (long)(Y / pow(10, yn0));

long D = (long)(Y % (long)pow(10, yn0));

long AC = CalculateUnSame(A, C, xn1, yn1);

long BD = CalculateUnSame(B, D, xn0, yn0);

long ABCD = CalculateUnSame((long)(A * pow(10, xn0) - B), (long)(D - C * pow(10, yn0)), xn1, yn1);

return (long)(2 * AC * pow(10, (xn0 + yn0)) + ABCD + 2 * BD);

}

}

c#语言:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace BigInteger

{

class Program

{

static void Main(string[] args)

{

SameNumber();

UnSameNumber();

}

static int SIGN(long A)

{

return A > 0 ? 1 : -1;

}

#region 两整数位数相同

private static void SameNumber()

{

Console.Write("请输入两个大整数:\nX=");

long X = Convert.ToInt64(Console.ReadLine());

Console.Write("Y=");

long Y = Convert.ToInt64(Console.ReadLine());

Console.Write("请输入两个大整数的长度:n=");

int n = Convert.ToInt32(Console.ReadLine());

long sum = CalculateSame(X, Y, n);

Console.WriteLine("普通乘法 X*Y={0}*{1}={2}\n", X, Y, X * Y);

Console.WriteLine("分治乘法 X*Y={0}*{1}={2}\n", X, Y, sum);

}

static long CalculateSame(long X, long Y, int n)

{

int sign = SIGN(X) * SIGN(Y);

X = Math.Abs(X);

Y = Math.Abs(Y);

if (X == 0 || Y == 0)

return 0;

else if (n == 1)

return sign * X * Y;

else

{

long A = (long)(X / Math.Pow(10, n / 2));

long B = (long)(X % Math.Pow(10, n / 2));

long C = (long)(Y / Math.Pow(10, n / 2));

long D = (long)(Y % Math.Pow(10, n / 2));

long AC = CalculateSame(A, C, n / 2);

long BD = CalculateSame(B, D, n / 2);

long ABCD = CalculateSame((A - B), (D - C), n / 2) + AC + BD;

return (long)(sign * (AC * Math.Pow(10, n) + ABCD * Math.Pow(10, n / 2) + BD));

}

}

#endregion

#region 两整数位数不相同

private static void UnSameNumber()

{

Console.Write("请输入两个大整数:\nX=");

long X = Convert.ToInt64(Console.ReadLine());

Console.Write("Y=");

long Y = Convert.ToInt64(Console.ReadLine());

Console.Write("请输入X的长度:xn=");

int xn = Convert.ToInt32(Console.ReadLine());

Console.Write("请输入Y的长度:yn=");

int yn = Convert.ToInt32(Console.ReadLine());

long sum = CalculateUnSame(X, Y, xn, yn);

Console.WriteLine("\n普通乘法 X*Y={0}*{1}={2}", X, Y, X * Y);

Console.WriteLine("分治乘法 X*Y={0}*{1}={2}\n", X, Y, sum);

}

static long CalculateUnSame(long X, long Y, int xn, int yn)

{

if (X == 0 || Y == 0)

return 0;

else if ((xn == 1 && yn == 1) || xn == 1 || yn == 1)

return X * Y;

else

{

int xn0 = xn / 2, yn0 = yn / 2;

int xn1 = xn - xn0, yn1 = yn - yn0;

long A = (long)(X / Math.Pow(10, xn0));

long B = (long)(X % Math.Pow(10, xn0));

long C = (long)(Y / Math.Pow(10, yn0));

long D = (long)(Y % Math.Pow(10, yn0));

long AC = CalculateUnSame(A, C, xn1, yn1);

long BD = CalculateUnSame(B, D, xn0, yn0);

long ABCD = CalculateUnSame((long)(A * Math.Pow(10, xn0) - B), (long)(D - C * Math.Pow(10, yn0)), xn1, yn1);

return (long)(2 * AC * Math.Pow(10, (xn0 + yn0)) + ABCD + 2 * BD);

}

}

#endregion

}

}

Java语言:

import java.util.ArrayList;

import java.util.Date;

import java.util.List;

import java.io.*;

import java.util.Scanner;

import java.util.Collections;

import java.util.Comparator;

import java.util.Random;

public class Program

{

public static Scanner sc = new Scanner(System.in);

public static int count=0;

public static void main(String[] args)

{

SameNumber();

UnSameNumber();

}

public static int SIGN(long A)

{

return A > 0 ? 1 : -1;

}

//两整数位数相同

private static void SameNumber()

{

System.out.print("请输入两个大整数:\nX=");

long X = sc.nextLong();

System.out.print("Y=");

long Y = sc.nextLong();

System.out.print("请输入两个大整数的长度:n=");

int n = sc.nextInt();

long sum = CalculateSame(X, Y, n);

System.out.println("普通乘法 X*Y="+X+"*"+Y+"="+X*Y+"\n");

System.out.println("分治乘法 X*Y="+X+"*"+Y+"="+sum+"\n");

}

public static long CalculateSame(long X, long Y, int n)

{

int sign = SIGN(X) * SIGN(Y);

X = Math.abs(X);

Y = Math.abs(Y);

if (X == 0 || Y == 0)

return 0;

else if (n == 1)

return sign * X * Y;

else

{

long A = (long)(X / Math.pow(10, n / 2));

long B = (long)(X % Math.pow(10, n / 2));

long C = (long)(Y / Math.pow(10, n / 2));

long D = (long)(Y % Math.pow(10, n / 2));

long AC = CalculateSame(A, C, n / 2);

long BD = CalculateSame(B, D, n / 2);

long ABCD = CalculateSame((A - B), (D - C), n / 2) + AC + BD;

return (long)(sign * (AC * Math.pow(10, n) + ABCD * Math.pow(10, n / 2) + BD));

}

}

//两整数位数不同

private static void UnSameNumber()

{

System.out.print("请输入两个大整数:\nX=");

long X = sc.nextLong();

System.out.print("Y=");

long Y = sc.nextLong();

System.out.print("请输入X的长度:xn=");

int xn = sc.nextInt();

System.out.print("请输入Y的长度:yn=");

int yn = sc.nextInt();

long sum = CalculateUnSame(X, Y, xn, yn);

System.out.println("普通乘法 X*Y="+X+"*"+Y+"="+X*Y+"\n");

System.out.println("分治乘法 X*Y="+X+"*"+Y+"="+sum+"\n");

}

public static long CalculateUnSame(long X, long Y, int xn, int yn)

{

if (X == 0 || Y == 0)

return 0;

else if ((xn == 1 && yn == 1) || xn == 1 || yn == 1)

return X * Y;

else

{

int xn0 = xn / 2, yn0 = yn / 2;

int xn1 = xn - xn0, yn1 = yn - yn0;

long A = (long)(X / Math.pow(10, xn0));

long B = (long)(X % Math.pow(10, xn0));

long C = (long)(Y / Math.pow(10, yn0));

long D = (long)(Y % Math.pow(10, yn0));

long AC = CalculateUnSame(A, C, xn1, yn1);

long BD = CalculateUnSame(B, D, xn0, yn0);

long ABCD = CalculateUnSame((long)(A * Math.pow(10, xn0) - B), (long)(D - C * Math.pow(10, yn0)), xn1, yn1);

return (long)(2 * AC * Math.pow(10, (xn0 + yn0)) + ABCD + 2 * BD);

}

}

}

JavaScript语言:

function SIGN(A)

{

return A > 0 ? 1 : -1;

}

function SameNumber()

{

var str = "";

var X = document.getElementById('SX').value;

var Y = document.getElementById('SY').value;

var n = document.getElementById('Sn').value;

var sum = CalculateSame(X, Y, n);

str += "普通乘法 X*Y="+X+"*"+Y+"="+X * Y+"
";

str += "分治乘法 X*Y="+X+"*"+Y+"="+sum;

document.getElementById('oldcontent').innerHTML = str;

}

function CalculateSame(X, Y, n)

{

var sign = SIGN(X) * SIGN(Y);

X = Math.abs(X);

Y = Math.abs(Y);

if (X == 0 || Y == 0)

return 0;

else if (n == 1)

return sign * X * Y;

else

{

var A = parseInt(X / Math.pow(10, n / 2));

var B = parseInt(X % Math.pow(10, n / 2));

var C = parseInt(Y / Math.pow(10, n / 2));

var D = parseInt(Y % Math.pow(10, n / 2));

var AC = CalculateSame(A, C, n / 2);

var BD = CalculateSame(B, D, n / 2);

var ABCD = CalculateSame((A - B), (D - C), n / 2) + AC + BD;

return (sign * (AC * Math.pow(10, n) + ABCD * Math.pow(10, n / 2) + BD));

}

}

function UnSameNumber()

{

var str = "";

var X = document.getElementById('KX').value;

var Y = document.getElementById('KY').value;

var xn = document.getElementById('xn').value;

var yn = document.getElementById('yn').value;

var sum = CalculateUnSame(X, Y, xn, yn);

str += "普通乘法 X*Y="+X+"*"+Y+"="+X * Y+"
";

str += "分治乘法 X*Y="+X+"*"+Y+"="+sum;

document.getElementById('newcontent').innerHTML = str;

}

function CalculateUnSame(X,Y,xn,yn)

{

if (X == 0 || Y == 0)

return 0;

else if ((xn == 1 && yn == 1) || xn == 1 || yn == 1)

return X * Y;

else

{

var xn0 = parseInt(xn / 2), yn0 = parseInt(yn / 2);

var xn1 = xn - xn0, yn1 = yn - yn0;

var A = parseInt(X / Math.pow(10, xn0));

var B = parseInt(X % Math.pow(10, xn0));

var C = parseInt(Y / Math.pow(10, yn0));

var D = parseInt(Y % Math.pow(10, yn0));

var AC = CalculateUnSame(A, C, xn1, yn1);

var BD = CalculateUnSame(B, D, xn0, yn0);

var ABCD = CalculateUnSame((A * Math.pow(10, xn0) - B), (D - C * Math.pow(10, yn0)), xn1, yn1);

return (2 * AC * Math.pow(10, (xn0 + yn0)) + ABCD + 2 * BD);

}

}

请输入两个大整数:X= Y= 请输入两个大整数的长度:n=
请输入两个大整数:X= Y= 请输入X的长度:xn=请输入Y的长度:yn=

PHP语言:

error_reporting(E_ALL ^ E_NOTICE);

SameNumber();

UnSameNumber();

function SameNumber()

{

fwrite(STDOUT, "理想状态算法!\n请输入两个大整数:\nX=");

$X = trim(fgets(STDIN));

fwrite(STDOUT, "Y=");

$Y = trim(fgets(STDIN));

fwrite(STDOUT, "请输入两个大整数的长度:n=");

$n = trim(fgets(STDIN));

$sum = CalculateSame($X, $Y, $n);

echo "普通乘法 X*Y=".$X."*".$Y."=".$X*$Y."\n";

echo "分治乘法 X*Y=".$X."*".$Y."=".$sum."\n";

}

function SIGN($A)

{

return $A > 0 ? 1 : -1;

}

function CalculateSame($X,$Y,$n)

{

$sign = SIGN($X) * SIGN($Y);

$X = abs($X);

$Y = abs($Y);

if ($X == 0 || $Y == 0)

return 0;

else if ($n == 1)

return $sign * $X * $Y;

else

{

$A = intval($X / pow(10, $n / 2));

$B = intval($X % pow(10, $n / 2));

$C = intval($Y / pow(10, $n / 2));

$D = intval($Y % pow(10, $n / 2));

//echo"sign=".$sign." pow=".pow(10, $n / 2)." X=".$X." Y=".$Y." A=".$A." B=".$B." C=".$C." D=".$D."\n";

$AC = CalculateSame($A, $C, $n / 2);

$BD = CalculateSame($B, $D, $n / 2);

$ABCD = CalculateSame(($A - $B), ($D - $C), $n / 2) + $AC + $BD;

//echo "sum=".( $AC * pow(10, $n) )." AC=".$AC." BD=".$BD." ABCD=".$ABCD."\n";

return ($sign * ($AC * pow(10, $n) + $ABCD * pow(10, $n / 2) + $BD));

}

}

function UnSameNumber()

{

fwrite(STDOUT, "\n非理想状态!\n请输入两个大整数:\nX=");

$X = trim(fgets(STDIN));

fwrite(STDOUT, "Y=");

$Y = trim(fgets(STDIN));

fwrite(STDOUT, "请输入X的长度:xn=");

$xn = trim(fgets(STDIN));

fwrite(STDOUT, "请输入Y的长度:yn=");

$yn = trim(fgets(STDIN));

$sum = CalculateUnSame($X, $Y, $xn,$yn);

echo "普通乘法 X*Y=".$X."*".$Y."=".$X*$Y."\n";

echo "分治乘法 X*Y=".$X."*".$Y."=".$sum."\n";

}

function CalculateUnSame($X,$Y,$xn,$yn)

{

if ($X == 0 || $Y == 0)

return 0;

else if (($xn == 1 && $yn == 1) || $xn == 1 || $yn == 1)

return $X * $Y;

else

{

$xn0 = intval($xn / 2);

$yn0 = intval($yn / 2);

$xn1 = $xn - $xn0;

$yn1 = $yn - $yn0;

$A = intval($X / pow(10, $xn0));

$B = intval($X % pow(10, $xn0));

$C = intval($Y / pow(10, $yn0));

$D = intval($Y % pow(10, $yn0));

echo"X=".$X." Y=".$Y." A=".$A." B=".$B." C=".$C." D=".$D."\n";

$AC = CalculateUnSame($A, $C, $xn1, $yn1);

$BD = CalculateUnSame($B, $D, $xn0, $yn0);

$ABCD = CalculateUnSame(($A * pow(10, $xn0) - $B), ($D - $C * pow(10, $yn0)), $xn1, $yn1);

//echo "sum=".( $AC * pow(10, $n) )." AC=".$AC." BD=".$BD." ABCD=".$ABCD."\n";

return (2 * $AC * pow(10, ($xn0 + $yn0)) + $ABCD + 2 * $BD);

}

}

?>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值