大數相乘-高精度乘法


一、算法簡要描述

    給定兩個數,相乘如何得到高精度的結果,給定的兩個數,不確定是不是浮點數,即可能一個數帶多位小數,另一個帶小數,或者兩個數都帶多位小數,或都不帶小數,針對這些情況,程序應該都要考慮,所謂的高精度其實就是看兩個數的小數位有多少,那么其結果的小數位數應該為兩數小數位數之和。

 

二、算法思路

   針對上述描述,其實大部分思路首先想到的應該是用字符串來表示這兩個數,帶小數點和不帶小數點最終都可轉換成類似於兩個大整數相乘的情況,在最后考慮把小數點放到結果的合適位置即可

 

三、算法代碼

 

 

/*
two float multipy, design a high-precision algorithm
*/

#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;

/*
* 函數:實現兩數相乘,並在合適位置插入小數點,posDot為兩數小數位數之和
*/
void big_multi(const char *str1,const char *str2,int posDot)
{
    int i,j;
    int len1=strlen(str1);
    int len2=strlen(str2);
    int rlen=len1+len2;
    int *pResult = new int[rlen];  //分配一個數組存儲計算結果,大小為兩數的位數之和
    memset(pResult,0,rlen*sizeof(int));
    //逐位相乘並放在相應位置,pResult[0]存放最終的進位,所以計算時是pResult[i+j+1]
    for(i=0;i<len1;++i)
    {
        for(j=0;j<len2;++j)
            pResult[i+j+1]+=(str1[i]-'0')*(str2[j]-'0');
    }
    //判斷逐位相乘的結果是否大於10,如果大於10要從后向前進位
    for(i=rlen-1;i>0;--i)
    {
        int t=pResult[i];
        if(t>9)
        {
            pResult[i-1] += t/10;
            pResult[i]=t%10;
        }    
    }
    //判斷結果開頭是否是以0開頭的,如果是要去掉
    i=0;
    while(pResult[i]==0)
        i++;
    //小數點位置應為從后往前posDot位
    j=i;
    while(j<rlen)
    {
        
        if(j==rlen-posDot)
            cout<<".";
        cout<<pResult[j];
        j++;
    }
    cout<<endl;
    
}
int main()
{

    string s1,s2;
    int pos1,pos2,posDot;
    while(cin>>s1>>s2)
    {
        if(s1=="quit")
            break;
        
        pos1=s1.find(".");
        pos2=s2.find(".");
        //計算兩數最終相乘結果的小數位數,有3種情況如下
        //兩數都有小數點的情況
        if(pos1!=string::npos && pos2!=string::npos)
            posDot = s1.length()+s2.length()-pos1-pos2-2;
        //其中一個有小數點的情況
        else if (pos2!=string::npos)
            posDot = s2.length()-pos2-1;
        //其中一個有小數點的情況
        else if (pos1!=string::npos)
            posDot = s1.length()-pos1-1;
        //在相乘之前,先把兩數中的小數點去掉,用stl的remove_if函數
        string::iterator newEnd1=remove_if(s1.begin(),s1.end(),bind2nd(equal_to<char>(),'.'));
        string::iterator newEnd2=remove_if(s2.begin(),s2.end(),bind2nd(equal_to<char>(),'.'));
        //去年小數點后,還要把新字符串結尾和原字符串結尾之間的多余字符刪除
        s1.erase(newEnd1,s1.end());
        s2.erase(newEnd2,s2.end());
        const char *str1=s1.c_str();
        const char *str2=s2.c_str();
        //cout<<str1<<" "<<str2<<" "<<posDot<<endl;
        big_multi(str1,str2,posDot);
    }
    
    return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM