大數相乘

使用分治法實現大數相乘,不要求兩數長度一致。時間複雜度爲T(N)=O(N^1.59).

#include <iostream>
#include <math.h>
using namespace std;
int SIGN(long A);
long CalculateUnSame(long X, long Y, int xn, int yn);
int main(int argc, char *argv[])
{
    cout<<"please input two numbers: \nX="; //若是用getline獲取string,則應用stringstream轉爲long.
    long X = 0;
    cin>>X;
    cout<<"Y=";
    long Y = 0;
    cin>>Y;
    int xn = 1;
    long x1 = X;
    while( x1 / 10 > 0) //求長度
    {
        xn++;
        x1 /= 10;
    }
    int yn = 1;
    long y1 = Y;
    while( y1 / 10 > 0)
    {
        yn++;
        y1 /= 10;
    }
    long sum = CalculateUnSame(X, Y, xn,yn);
    cout<<"normal mult_result X * Y = "<<X<<" * "<<Y<<" = "<<X * Y<<endl;
    cout<<"divide and conqure X * Y = "<<X<<" * "<<Y<<" = "<<sum<<endl;
    return 0;
}
int SIGN(long A)
{
    return A > 0 ? 1 : -1;
}
long CalculateUnSame(long X, long Y, int xn, int yn)
{
    int sign = SIGN(X) * SIGN(Y);
    X = abs(X);
    Y = abs(Y);
    if (X == 0 || Y == 0)
        return 0;
    else if (xn == 1 || yn == 1)
        return  sign * 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) sign * (2 * AC * pow(10, (xn0 + yn0)) + ABCD + 2 * BD);
    }
}

上述代碼中數據類型定義爲long,而在limits.h中可以看到:long型數最大值爲2147483647,最小值爲-2147483648

開根號得46340,五位數。所以上面代碼計算結果大於 LONG_MAX時就會溢出。

將數據類型改爲long long可以計算的結果爲:最大值9223372036854775807,最小值-9223372036854775808

根號9223372036854775807得到3037000500,10位數。

不管是long還是long long都有長度限制。所以本算法並不能真正做到大數相乘。進一步的改進是將數據都用string來傳遞。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章