青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

elva

大數四則運算的C++實現

大數四則運算的C++實現



[摘要] 大數運算不僅僅運用在密碼學中,還運用在一些物理學研究、生物學,化學等科目中。大數運算,意味著參加的值和計算結果通常是以上百位數,上千位數以及更大長度之間的整數運算。例如大家所熟知圓周率π的值,在一般的數值計算中用到圓周率的不須要多大的精度,但在計算一些星球或是星系上的體積面積時便顯的誤差很大了,這就要求π值計算的精度達到幾百萬位甚至更高,才能縮小誤差。人工計算是遠遠不行了,而且本身誤差也無法估計。只有在計算機中用大數運算求π值了。又如,考古學家計算石頭內的碳元素衰變來考證地球形成的時間,更是將計算的結果精確到了百年以內。所以說大數的運算是涉及領域多,應用范廣,與我們生活息息關。在此,我采用一個在C語言下實現計算大數運算的一個程序為例,講解包括了大數的加法,減法,乘法和除法及求冪運算的算法及代碼。

[關鍵詞] 大數計算 網絡安全 密碼學







    隨著計算機網絡技術的發展和因特網的廣泛普及,網絡安全事故逐年增加,黑客的攻擊已經和病毒并列成為對信息安全影響最嚴重的兩大危害。其很大程度上是被黑客破解了用戶的計算機名及登陸密碼及資料的加密較差,而使得黑客來對網民的資料如同自己般的隨意更改和破壞。而安全的密碼和賬號成為了網民的安全之本,怎么才能提高安全問題成為的人們和社會關注的問題。而加密大部又是以大素數的計算為基礎的,如非對稱密碼體制RSA的安全性依賴于對大數進行因數分解的耗時性。一個二進制數n的因數分解所需的機器周期大約是exp{[ln(n)ln(ln(n))]1/2}。若機器周期為1μs,b為二進制數的位數,分解 n=2b 所需時間如下表所示:

位數 100 200 300 500 750 1000
時間 30秒 3天 9年 1兆年 2*109年 6*1015年

    實際應用中,p、q的選擇都在10200 數字以上,這樣每個明文塊的二進制位數可達664比特,即83個字節。而DES只有8個字符。一般認為,對于當前的計算機水平,選擇1024位長的密鑰就可認為是無法攻破的了。


1. 數字存儲的實現
    大數計算的因數和結果精度一般是少則數十位,多則幾萬位。在C語言中定義的類型中精度最多只有二十多位,因而我們采取用鏈表存貯的方式來存放大數。在計算中會用到從高位開始計算,和從低位開始計算數值的兩種情況。所以我們將鏈表定義為雙向鏈表,其中為一個單元來存貯數據,一個指針指向前方的數據,另一個指向后的數據。其結構為:

struct Node    // 定義一個雙向鏈表用來存貯結果
{
char data;     // 數據*定義為字符的原因:要顯示負號
Node *next;    // 尾指針
Node *ahead;   // 首指針
};

 

2. 各種算法
2.1 加法運算的實現
    加法計算還是比較容易的,我們也是先從低位算起,因為只須要對應的位相加,再加上前一位的進位,再去判斷是否本位是否有進位, 有則把本位數字改為減去它的權,也就是10,再置進位為1。如果沒有進位,則給進位賦值0。

    在程序時應注意:
    1、兩個加數中那一個數的位數長,以位數長的作為循環變量;
    2、結束循環時,不僅僅是最后一位加完就停止,還應加入如果有進位,也要再循環一次。如最后一位是9,進位是1,則相加時進位,要加上進位這一位值。具體看代碼,輸入輸出時和乘法的一樣。
/*--------------------------------------------------------------------------
*函數名稱: 大數加法
*函數過程:1 比較兩個數那一個長
* 2 以長的作為循環次數
* 3 對應項相加 進位存貯直到下高位相加用
* 4 直到循環結束
* 5 !!!!!!沒設計負數相加
*入口參數:numa,numb,result字符串
*出口參數:無
*編輯環境:winSP2 + VC2003 + C++
*--------------------------------------------------------------------------*/

void addition(char *numa, char *numb,char *result) // 計算兩大數之和
{
  char *pna = findend(numa); // 指向numa的一個指針。point numa pna 指向乘數的最低位,
  char *pnb = findend(numb); //指向numb的一個指針 //pnb 指向被乘數的最低位,
  int along=(int)strlen(numa); //標記數字a的長度;
  int blong=(int)strlen(numb); //標記數字b的長度;
  int times = 0; // 標致要計算多少次。
  int carry=0,temp_result; //存貯進位 和臨時結果的
  Node *head, // 用于存貯頭指針
    *pstart, // 用于存貯計算時的首指針
    *pnew; //作于申請新結點
  head = pstart =new Node; //初始化首結點和頭結點。
  pstart -> data = 0;
  pstart -> next = NULL;
  pstart -> ahead = NULL;

  if (abigerb(numa ,numb)>=1)
  times = (int)strlen(numa); //比較兩個字符串長度,以大的作為循環次數
  else
    {
      times = (int)strlen(numb);
      pna = findend(numb); //交換指針
      pnb = findend(numa);
    along=(int)strlen(numb); //標記數字a的長度;
    blong=(int)strlen(numa); //標記數字b的長度;
    }
    while ((times-- && (times>=0))|| carry != 0)
    {
      if(!pstart->next) //如果當前為空結點,則申請新結點
      {
        pnew = new Node;
        pnew -> data = 0;
        pnew -> next = NULL;
        pnew -> ahead = pstart;
        pstart -> next = pnew;
      }
      else temp_result =(pstart->data +(*pna-48)+(*pnb-48)+carry) ; //自身的值+新值+進位 作為當前的新值

      pstart -> data = temp_result%10; //存貯個位
      carry = temp_result/10; //存貯進位
      pstart = pstart -> next; //結點移動
    blong--;
      if(blong>0)pnb--; //指針移向被加數高位
      else *pnb=48; //之后相減就變為了0不作任何運算;
      pna--; //加數指針移動,
    }
  pstart =head; //尋找鏈表的結尾點
  while(pstart->next != 0)
  {
  pstart->data += 48; //!!<<<因為我們的輸出是字符。所以再此加上48>>>> 逆順輸出
  pstart = pstart->next ;
  }

  int tip = 0; //轉為字符串用
    pstart = pstart->ahead ; //找有效字
     //cout<<"\n結果是 : ";
    while(pstart != 0) //輸出正序的結果;
    {
    result[tip++] = pstart->data;
     //cout< data;
    pstart = pstart->ahead ;
    }
    result[tip] = '\0';

  pstart =head; //釋放空間
  while(pstart->next != 0)
  {
  pnew = pstart->next ;delete pstart;
  pstart =pnew;
  }
  return ;
}
2.2 減法運算的實現
    減法稍微有一點復雜, 因為會處理負數,而我們所用的是字符串的形式來保存數字也是為這一點。否則用整型或其它類型時,則表示處理、保存時會相當復雜。算法也是從低位開始減。先要判斷減數和被減數那一個位數長,減數位數長是正常減;被減數位數長,則被減數減減數,最后還要加上負號;兩數位數長度相等時,最好比那一個數字大,否則負號處理會很繁瑣;處理每一項時要,如果前一位相減有借位,就先減去上一位的借位,無則不減,再去判斷是否能夠減開被減數,如果減不開,就要借位后再去減,同時置借位為1,否則置借位為0。
    這有一我寫的比較兩個數字符串大小的函數:
//返回值說明:0是alongblong ; 2是along=blong
int abigerb(char *numa, char *numb) //比較兩個數最高位那一個大
{
  int along=(int)strlen(numa); //標記數字a的長度;
  int blong=(int)strlen(numb); //標記數字b的長度;
  char *pna = numa; //指向數A的最高位,
  char *pnb = numb; //指向數B的最高位,
  if (along>blong) return 1;
  if (along==blong)
  {
    while(*pna) //比較兩個數那一個大
    {
      if(*pna>*pnb)return 1;
      else if(*pna<*pnb)return 0 ;
      else if(*pna==*pnb){pna++;pnb++;} //1111與1112
    }
    return 2; //這表明找到最后了還是全相等;
  }
  return 0 ;
}
    在程序時應注意:
    1、如果被減數大于減數時,指針和相應循環長度控制變量也要做相應的修改。
    2、結果可能會出現前面是一堆0的情況,要處理好,如當減數為11112,而被減數為11111時,會出現00001,處理過程見代碼。
/*--------------------------------------------------------------------------
*函數名稱: 大數減法
*函數過程:1 比較兩個數那一個長
* 2 以長的作為循環次數
* 3 如果兩個數長度相等,從最高位開始比直到發現那一個數更大,使大項減去小項
* 4 對應項相減 進位存貯直到下高位相加用
* 5 每一位對應項相減時,處理三種可能的情況,a=b,ab;
* 6 a=b時,則計算,11-12,111-112,要考慮借位
* 7 直到循環結束
*入口參數:numa,numb,result字符串
*出口參數:無
*--------------------------------------------------------------------------*/

void subtract(char *numa, char *numb,char *result)//計算減
            {
            char *pna = findend(numa);//指向numa的一個指針。point numa      pna 指向減數的最低位,
            char *pnb = findend(numb);//指向numb的一個指針                 //pnb 指向被減數的最低位,
            int  along=(int)strlen(numa);//標記數字a的長度;
            int  blong=(int)strlen(numb);//標記數字b的長度;
            int  times = 0;         // 標記要計算多少次。
            int  carry=0;           //存貯借位
            int  clear0=0;          //消除結果最前面無用的'0'  13-5 = 08 的效果!!
            int  isnegative=0;      //用來加上被減數大于減數時補上最后一個負號
            Node *head,   // 用于存貯頭指針
            *pstart,  // 用于存貯計算時的首指針
            *pnew;    //作于申請新結點
            head = pstart =new Node;//初始化首結點和頭結點。
            pstart -> data = 0;
            pstart -> next = NULL;
            pstart -> ahead = NULL;
            if (abigerb(numa ,numb))
            times = strlen(numa);//比較兩個字符串長度,以大的作為循環次數
            else //交換位置以降低難度
            {
            times = strlen(numb);//讓數(字符串)長的減去數(字符串)短的
            pna = findend(numb);//交換指針
            pnb = findend(numa);
            along=(int)strlen(numb);//標記數字a的長度;
            blong=(int)strlen(numa);//標記數字b的長度;
            isnegative=1;//標記最后要加上負號
            }
            while ((times-- && (times>=0))|| carry != 0)//carry != 0 說沒有借位時
            {
            if(!pstart->next)//如果當前為空結點,則申請新結點
            {
            pnew = new Node;
            pnew -> data = 0;
            pnew -> next = NULL;
            pnew -> ahead = pstart;
            pstart -> next = pnew;
            }
            if(times<0)//如果計算完之后,借位等于1,,說明必然為負值;
            {
            pstart -> data  = -3 ;//讓它等于負號 '-'//-3來源于負號與0相差3。。                break;
            }
            else
            {
            if ( *pna == *pnb )//減數等于被減數時。結果等于直截相減的結果;并置借位為0
            {
            if(carry==0)pstart -> data = (*pna-48)-(*pnb-48); //111-11的情況
            else
            {
            pstart->data = (*pna-48)-(*pnb-48)+10 -carry;//1121-1112
            carry=1;
            }
            }
            if( *pna > *pnb )//減數大于被減數時。結果等于直截相減的結果;并置借位為0
            {
            pstart -> data = (*pna-48)-(*pnb-48)-carry;  //存貯個位
            carry=0;
            }
            else if( *pna < *pnb )//說明被減數大于減數,讓結果加10,相當于借位 (carry)為1
            {
            if(times>0) pstart->data = (*pna-48)-(*pnb-48)+10 -carry;//13-5的情況作為新值
            else  pstart->data = (*pnb-48)-(*pna-48) -carry; //3-5  作為當前的新值
            carry=1;
            }
            }
            pstart = pstart -> next;          //結點移動
            blong--;
            if(blong>0)pnb--;//指針移向被減數高位
            else *pnb=48;//之后相減就變為了0不作任何運算,其實可以優化的。但代碼會長!而且還需要重新開結點。所以放棄;
            pna--;//被數指針移動,
            }
            if(isnegative==1)////加上負號處理。增加一長度并置為負號
            {
            pnew = new Node;
            pnew -> data = 0;
            pnew -> next = NULL;
            pnew -> ahead = pstart;
            pstart -> next = pnew;
            pstart->data=-3;//因為尋找鏈表的結尾點要統一加48。又因為‘-’是45。所以等于‘-3’
            }
            pstart =head;//尋找鏈表的結尾點
            while(pstart->next != 0)
            {
            pstart->data += 48;//!!<<<因為我們的輸出是字符。所以再此加上48>>>>  逆順輸出
            pstart = pstart->next ;
            }
            int tip = 0;//轉為字符串用
            clear0=0;//  消除結果最前面無用的'0'  13-5 = 08 的效果  ..>>修改字符串的首指針
            pstart = pstart->ahead ;//找有效字
            while(pstart != 0)//輸出正序的結果;
            {
            if (clear0==0 && ((int)pstart->data)==48&&pstart->ahead!=0)//  消除結果最前面無用的'0'
            ;//不輸出任何東西
            else
            result[tip++] = pstart->data;
            if(((int)pstart->data)!=48&&((int)pstart->data)!=45)clear0=1;//'-'號
            pstart = pstart->ahead ;
            }
            result[tip] = '\0';
            pstart =head;  //釋放空間
            while(pstart->next != 0)
            {
            pnew = pstart->next ;delete pstart;
            pstart =pnew;
            }
            return ;
            }
            


2.3 乘法運算的實現
    首先說一下乘法計算的算法,從低位向高位乘,在豎式計算中,我們是將乘數第一位與被乘數的每一位相乘,記錄結果,之后,用第二位相乘,記錄結果并且左移一位,以此類推,直到計算完最后一位,再將各項結果相加。得出最后結果。當然我們可以直接用這種方法,但要用多個鏈表來保存計算出的分結果, 之后結果再相加得到最后結果,但是這樣會浪費很多空間,我們可以再優化一下,就是只用一人鏈表來表示結果,先把第一位乘數與被乘數的結果保存在鏈表中,之后把存儲結果的頭部后移一位、也就是從鏈表的第二加起,當第二位乘數與被乘數結果加到第二之后的各個項內。以此類推,直到結束。這樣就可以用一個鏈表來存儲相乘后的結果。
    在程序時應注意:
    1、傳入的乘數和被乘數是以字符串形式放入的話,要讓指針指向最后一位,我自己寫了個函數來完成這件事。鏈表傳入也要找到最后一向來計算;
    2、因為傳入和保存的都是字符,所以計算時要將字符轉化為數字,算完再轉化為字符存儲;
    3、另外進位時要處理,當前的值加上進位的值再看本位數字是否又有進位;
    4、輸出時要逆序輸出,因為鏈表首指針是存的結果的最低位。我的函數為了對應輸入輸出結果的一致性,都有采用了字符串輸出,所以在輸出時又將鏈表轉為了字符串。
    具體代碼如下:
/*--------------------------------------------------------------------------
*函數名稱: 大數乘法
*函數過程:1 輸入兩個大數作為字符串
* 2 作一個雙向鏈表
* 3 兩個指針分別指向數字字符串的最低位
* 4 以第一個數的最低的一個位乘以第二個數的所有項存于鏈表中
* 5 鏈表首指針移
* 6 重復4,5依次從最低位乘到最高位
* 7 乘完后因為最低位是鏈表首,最后一位是鏈表尾。所以在逆順輸出鏈表。
* 4 直到循環結束
*入口參數:numa,numb,result字符串
*出口參數:無
*--------------------------------------------------------------------------*/
void multiply(char *numa, char *numb ,char *result)//用來儲結果的)//計算乘積
            {
            char *pna = findend(numa);//指向numa的一個指針。point numa      pna 指向乘數的最低位,
            char *pnb = findend(numb);//指向numb的一個指針                 //pnb 指向被乘數的最低位,
            int along=(int)strlen(numa);//標記數字a的長度;
            int blong=(int)strlen(numb);//標記數字b的長度;
            int  carry=0,temp_result;//存貯進位  和臨時結果的
            Node *head,   // 用于存貯頭指針
            *pstart,  // 用于存貯計算時的首指針
            *pnew,    //作于申請新結點
            *pgo;     //作為每計算完一行時,回到下一行起始節點用,移位標致來用
            head = pstart =new Node;//初始化首結點和頭結點。
            pstart -> data = 0;
            pstart -> next = NULL;
            pstart -> ahead = NULL;
            while (along--)
            {
            pgo = pstart;//保存進位點
            blong = (int)strlen(numb);//初始化長度
            pnb = findend(numb); //初始化指針
            while ((blong-- && (blong>=0))|| carry != 0)
            {
            if(!pstart->next)//如果當前為空結點,則申請新結點
            {
            pnew = new Node;
            pnew -> data = 0;
            pnew -> next = NULL;
            pnew -> ahead = pstart;
            pstart -> next = pnew;
            }
            if(blong<0)temp_result = carry ;//處理只有進位的情況
            else temp_result =(pstart->data+(*pna-48)*(*pnb-48)+carry);//自身值+新值+進位作為新值
            pstart -> data = temp_result%10;  //存貯個位
            carry = temp_result/10;           //存貯進位
            pstart = pstart -> next;          //結點移動
            pnb--; //指針移向被乘數高位
            }
            pstart = pgo->next; //前進一個位置;
            pna--;   //指針移向乘數高位
            }
            pstart =head;//尋找鏈表的結尾點
            while(pstart->next != 0)
            {
            pstart->data += 48;//!!<<<因為我們的輸出是字符。所以再此加上48>>>>  逆順輸出
            pstart = pstart->next ;
            }
            int tip = 0;//轉為字符串用
            pstart = pstart->ahead ;//找有效字
            while(pstart != 0)//輸出正序的結果;
            {
            result[tip++] = pstart->data;
            pstart = pstart->ahead ;
            }
            result[tip] = '\0';
            pstart =head;  //釋放空間
            while(pstart->next != 0)
            {
            pnew = pstart->next ;delete pstart;
            pstart =pnew;
            }
            return ;
            }
            


2.4 除法運算的實現
    首先說一下我們所要的結果,當除數除不開被子除數時,不用除到小數,當除數小于被除數時,除數作為余數既可,不用再向下除了。
    除法算法是最容易想到的啦!我們學數字電路,或模擬電路時里面有用門實現的除法器,做法是用除數減被除數,再用一個加法器去計算存儲結果,算法簡單明了,結果我實現之后,計算速度大大出乎我的遇料,比算乘方時還慢,經仔細想想電路中計算的長度不過8位,16位,32位,而且都是硬件實現,我們要算的是幾千位,幾萬位。特別是兩數位長度差很大時計算速度相當慢,如10000-3時要進行多少次鏈表運算啊。
    否定了這條算法,經不斷思考,發現另一種方法可行,且效率僅次于減法。就是從高位向低位減,減時以被除數長度為單位,從高位取出大于被除數的字符串,和被除數相減,減的次數為結果,余數從剩下的除數高位再取出幾位做補位,直到大于被除數。再減,循環減到被減數大于余數加上補位,那么這個新的余數作為結果返回。
    在程序時應注意:
    1、除法算法計算時是用的最高位開始向低位減,所以要注意指針的位置。
    2、余數和被減數相減時,一定要注意:一旦能夠減開被除數時,一定要每從除數那里取一個字符時,結果也要對應補一個0。如111222/111。
/*--------------------------------------------------------------------------
*函數名稱: 大數除法2--
*函數想法:1 用指針指向除數的最高位,保存臨時字符串; tempstr[a++] = pna
* 2 如果臨時字符串大于被除數,則相減。結果等于余數
* if(tempstr>numb)tempstr = tempstr - numb
* 3 如果小于被除數且指針到頭,余數 等于 臨時字符串
* if(tempstr *
*入口參數:numa,numb,result,remainder字符串
*出口參數:無
*--------------------------------------------------------------------------*/
void divide2( char *numa, char *numb,char *result,char *remainder)//計算除法2
            {
            char one[]="1";//臨時字符串....
            char one2[]="1";//
            char zero[]="0";//
            char numb2[6048];//
            char tempstr[6018]="";//臨時字符串
            int  ia=0,ia2=0;//tempstr的指示器
            bool  moveon=false;//翻轉牌
            char *pna = numa;//指向numa的一個指針。point numa      pna 指向減數的最低位,
            char *pnb = findend(numb);//指向numb的一個指針                 //pnb 指向被減數的最低位,
            Node *head,   // 用于存貯頭指針
            *pstart,  // 用于存貯計算時的首指針
            *pnew;    //作于申請新結點
            head = pstart =new Node;//初始化首結點和頭結點。
            pstart -> data = 0;
            pstart -> next = NULL;
            pstart -> ahead = NULL;
            moveon = false;
            while(*pna)
            {
            if(!pstart->next)//如果當前為空結點,則申請新結點
            {
            pnew = new Node;
            pnew -> data = 0;
            pnew -> next = NULL;
            pnew -> ahead = pstart;
            pstart -> next = pnew;
            }
            ia=(int)strlen(tempstr);//取的長度
            tempstr[ia++] = *(pna++);
            tempstr[ia] ='\0'; //轉換為字符串
            if(tempstr[0]=='0')//處理高位也是0的那種 如00
            {
            ia2=0;
            while(tempstr[ia2]=='0')++ia2;
            while(ia2>=1)//清除無用的0
            {
            ia=ia2-1;
            tempstr[ia]=tempstr[ia2];
            --ia2;
            }
            tempstr[++ia2]='\0';
            }
            while(abigerb(tempstr,numb)>0)//如果tempstr大于等于numb
            {
            if(tempstr[0]=='0')//處理高位也是0的那種 如00----此乃冗余代碼,留做記念用
            {
            ia2=0;
            while(tempstr[ia2]=='0')++ia2;
            if(ia==ia2 )
            {
            moveon = true;
            break;
            }
            }
            strcpy(numb2,numb);
            subtract(tempstr, numb,tempstr);//A-B
            strcpy(numb,numb2);
            if(tempstr[0]=='-')//若判斷的不準,變為了負數就再加上B。。
            {
            strcpy(numb2,numb);
            addition(tempstr, numb,tempstr);//A-B
            strcpy(numb,numb2);
            ia2=0; //修正之后的長度。因為加法中未做負數運算
            ia=0;  //為了消除最后的那一個負號,整體向前移動。
            while(tempstr[ia2]!='\0')++ia2;
            while(ia2>=1)//清除無用的0
            {
            tempstr[ia]=tempstr[ia+1];
            ++ia;
            --ia2;
            }
            tempstr[ia]='\0';
            moveon = true;
            break;
            }
            pstart->data++ ; //結果自加
            moveon = true;
            }
            if(moveon) pstart = pstart -> next;          //結點移動
            }
            strcpy(remainder,tempstr);//存貯余數
            int tip = 0;//轉為字符串用
            pstart =head;//尋找鏈表的結尾點
            while(pstart->next != 0)
            {
            pstart->data += 48;//!!<<<因為我們的輸出是字符。所以再此加上48>>>>  逆順輸出
            result[tip++] = pstart->data;
            pstart = pstart->next ;
            }
            result[tip] = '\0';//存貯結果
            pstart =head;  //釋放空間
            while(pstart->next != 0)
            {
            pnew = pstart->next ;delete pstart;
            pstart =pnew;
            }
            return ;
            }
            


2.5 冪運算的實現
    冪的實現是最為簡單的了,國為有了前面的算法做鋪墊,就是調用乘法函數,來循環去自乘,冪指數相應減1,直到冪指數變為0時結束。其詳細代碼如下:

/*--------------------------------------------------------------------------
*函數名稱: 大數冪
*函數想法:1 B自減1直到,,作為循環控制變量.保存結果;
* 2 結果初值1 每次乘以A
* 3 重復1、2步驟到結束.
*入口參數:numa,numb,result字符串
*出口參數:無
*--------------------------------------------------------------------------*/

void power (char *numa, char *numb,char *result) //計算冪
{ char one[]="1"; //臨時字符串....
char one2[]="1";
char zero[]="0";
char numb2[6048];
char remainder[6048];
strcpy(result,one); //給結果初值為1
strcpy(numb2,numb);

subtract(numb,one ,remainder); //B自減1
strcpy(numb,numb2);

strcpy(numb2,numb);
multiply(result,numa,result ); //A自己乘自己
strcpy(numb,numb2);

while(strcmp(remainder,zero)>0) //A大于相等B時 就是numb不等于0時
{
strcpy(numb2,numb);
multiply(result,numa,result ); //A自己乘自己
strcpy(numb,numb2);
strcpy(one,one2);
subtract(remainder,one ,remainder); //B減一
}

return ;
}

 

3. 程序運行介面
    程序的介面制作就不多加描述了,以下是我的大數程序的運行介面。


4. 總結與評價
    1) 本文主旨是對算法加以了實現,但未做相應的優化。因為本文的目地是對大數運算的過程產生一個具體設計方法與實現思路。而還是不是工程上能所直接應用的。當然在要作中是也許用的設計語言并不是C語言,可能是JAVA、 C++、 Delphi 、PHP等等。但不管是什么樣的設計語言,設計思路都是相同的。
    2) 關于代碼和算法優化問題,本文中代碼并不是簡短,高效。現在對此說明個人認為在工程要改正的幾個方面。首先每個鏈表節點的元素所存的數據小的可憐,只存儲了一位數據,但這是最容易想到的,模仿十進制那樣進位。但這并沒考慮機器的計算的情況,在我們常用的32位計算中,CPU中加減乘除的一次運算是32位的值,也就是說2的32次方的一個值,這就是說1加上1的CPU工作量和小于2的32的兩位數相加是用的相同的周期。如下圖所示:
    為避免運算結果大于2的32次,因為大于的話又會造成一次CPU周期運算,但這樣當然也可以做。但建議用下面方法,考慮乘法的原因,兩個2的16次方相乘就是2的32次方的情況,所以我們可以定義每個鏈表節點值為2的16次方,也就是 18446744073709551616的一個整數值,C++語言中_int64類型的范圍就是這么大。再把它當作以前處理十進制的權10去處理,效率會翻2的16方倍了。結點數巨減,主要是開內存方面,有了極大的減少。
    3) 另外本程序中是用數組去傳遞參數的,這非常不好,而且會限制你結果的長度。只有一點好處,易懂!個人認為工程中,一定要用鏈表指針來傳遞參數, 這樣就解決了可算到無限長的問題。只是釋放鏈表時要在最后用完再釋放了。對于本文用的方法就顯得明了多了。
    4) 總體來說本文重在說明方法,效率較差。工作時定要注重效率問題。在C++系列下的程序盡量多用庫函數,會減少大量的代碼。適當的去加入些匯編以提高效率。

 

5. 軟件下載演示
點擊下載大數運算軟件

6. 參考文獻
1. 李藝《網絡安全講義》PPT文檔
2. 譚浩強《C程序設計》第二版,清華大學出版社
3. Adam Drozdek《數據結構與算法》第三版,清華大學出版社
4. 何德全《網絡安全》清華大學出版社
5. http://www.tup.com.cn

posted on 2007-08-15 13:21 葉子 閱讀(13636) 評論(8)  編輯 收藏 引用 所屬分類: C\C++

Feedback

# re: 大數四則運算的C++實現 2007-10-29 09:29 Sailing

學習了哦  回復  更多評論   

# re: 大數四則運算的C++實現 2007-12-24 00:37 秦歌

好東西,學習了  回復  更多評論   

# re: 大數四則運算的C++實現 2009-08-09 13:43 大牛

你的大數加法有點問題  回復  更多評論   

# re: 大數四則運算的C++實現 2009-08-10 19:27 葉子

@大牛
啥問題?說說  回復  更多評論   

# re: 大數四則運算的C++實現 2010-02-15 08:20 BJ.Paul


怎么說呢?


主要在效率方面;

用struct 來規劃表達大數,未免將雙鏈表用的不是地方,

首先,操作大數不方便;
其次,效率不是很高;


就說加法吧,需要那么多語句來完成一個簡單的加法,
實在怪異的很;

大數中, 1,0,-1,是極其常用常數,沒有統一的表達;


這樣的解決方案,要比openssl的解決方案慢許多。

加油!  回復  更多評論   

# re: 大數四則運算的C++實現 2010-02-22 02:35 OpenHero

把char修改成int32,性能會更高:)  回復  更多評論   

# re: 大數四則運算的C++實現 2011-06-11 16:31 coaku

對,LZ你的加法有問題,字符串指針指錯了,其他還沒看  回復  更多評論   

# re: 大數四則運算的C++實現 2011-11-26 17:31 someone

乘法你沒有考慮當兩個數的位數非常多時,加法導致整數溢出問題  回復  更多評論   

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲欧美久久久| 性欧美办公室18xxxxhd| 亚洲久久在线| 亚洲电影免费观看高清完整版| 国产欧美精品一区aⅴ影院| 欧美日韩不卡合集视频| 欧美极品一区二区三区| 欧美日本在线播放| 国产精品成人观看视频国产奇米| 欧美三级特黄| 国产精品一区二区a| 夜夜嗨av一区二区三区网页| 久久亚洲春色中文字幕久久久| 欧美一区二区三区在线观看| 久久国产主播| 亚洲成人中文| 欧美激情精品久久久久久免费印度 | 最新成人av在线| 欧美国产精品va在线观看| 亚洲人成啪啪网站| 中国日韩欧美久久久久久久久| 午夜精品国产更新| 亚洲中字在线| 久久久综合视频| 欧美电影在线观看完整版| 亚洲国产精品va在线看黑人 | 亚洲在线观看| 久久午夜精品一区二区| 欧美日韩视频第一区| 国内精品美女av在线播放| 亚洲美女免费精品视频在线观看| 亚洲欧美电影在线观看| 在线日韩中文| 亚洲男人影院| 亚洲人成网站777色婷婷| 亚洲嫩草精品久久| 欧美精品三区| 黄色亚洲大片免费在线观看| 日韩一级裸体免费视频| 亚洲欧洲日产国产网站| 9l国产精品久久久久麻豆| 亚洲伊人伊色伊影伊综合网| 男女视频一区二区| 国产一区二区三区观看| 亚洲一区中文| 亚洲精品123区| 久久久久久久999精品视频| 国产精品久久久久久亚洲调教| 亚洲经典在线看| 久久国产精品99久久久久久老狼| 99精品国产在热久久婷婷| 欧美成年网站| 亚洲美女一区| 亚洲国产第一页| 久久久人成影片一区二区三区| 国产女人水真多18毛片18精品视频| 宅男66日本亚洲欧美视频| 亚洲国产另类精品专区| 免费成人高清在线视频| 久久久欧美精品sm网站| 黑人一区二区| 久久欧美肥婆一二区| 亚洲欧美国产精品va在线观看| 欧美日韩中文字幕精品| 亚洲伦伦在线| 最新国产の精品合集bt伙计| 欧美成熟视频| 亚洲精品欧美专区| 亚洲一级在线观看| 国产精品亚洲不卡a| 亚洲欧美成人精品| 午夜精品视频在线观看| 国外成人网址| 欧美成年人网站| 蘑菇福利视频一区播放| 亚洲精品久久在线| 亚洲精选91| 蜜桃视频一区| 亚洲欧美久久久| 欧美婷婷久久| 亚洲综合大片69999| 一区二区三区视频在线观看| 欧美日韩国产探花| 午夜精品久久久| 亚欧美中日韩视频| 在线欧美亚洲| 99成人在线| 中文亚洲欧美| 国产欧美日韩另类视频免费观看| 欧美一区中文字幕| 久久久欧美精品| 宅男噜噜噜66一区二区| 亚洲一区二区在线免费观看视频 | 亚洲午夜视频在线| 亚洲自拍偷拍色片视频| 国内外成人免费视频| 欧美成人黄色小视频| 欧美日本高清一区| 久久精品视频免费播放| 久久综合伊人77777麻豆| 一区二区激情视频| 亚久久调教视频| aⅴ色国产欧美| 欧美专区日韩专区| 一本色道久久综合亚洲精品高清| 亚洲一区免费观看| 亚洲国产欧美一区二区三区同亚洲 | 一区二区三区日韩欧美精品| 亚洲一区免费| 亚洲美女精品久久| 久久永久免费| 国产日韩综合一区二区性色av| 9人人澡人人爽人人精品| 久久成人精品电影| 亚洲视频在线播放| 美女性感视频久久久| 性感少妇一区| 欧美日韩你懂的| 免费成人黄色片| 久久爱另类一区二区小说| 一区二区三区四区精品| 亚洲国产午夜| 久久蜜桃精品| 久久夜色精品| 国产在线观看一区| 午夜精品久久久久久久99樱桃| av成人激情| 欧美激情性爽国产精品17p| 巨乳诱惑日韩免费av| 国产视频亚洲精品| 亚洲欧美日韩视频一区| 亚洲欧美日韩国产综合| 欧美日本高清一区| 日韩一二三区视频| 亚洲欧美日韩精品综合在线观看| 欧美不卡视频一区| 美女爽到呻吟久久久久| 国产精品久久久久婷婷| 日韩亚洲成人av在线| 欧美精品粉嫩高潮一区二区| 麻豆国产精品一区二区三区| 国产日韩一区二区三区在线播放| 这里只有视频精品| 亚洲综合视频网| 国产精品久久影院| 亚洲伊人网站| 麻豆成人综合网| 亚洲免费激情| 国产精品扒开腿做爽爽爽视频| 国产精品高潮粉嫩av| 一区二区三区视频在线| 午夜精品亚洲一区二区三区嫩草| 欧美日韩国产黄| 亚洲一区二区三区成人在线视频精品| 亚洲性xxxx| 国产日韩av一区二区| 久久国产88| 亚洲国产天堂久久综合| 99精品99| 国产精品嫩草影院av蜜臀| 亚洲欧美影音先锋| 男男成人高潮片免费网站| 亚洲国产一区二区精品专区| 欧美大片在线观看一区| 一区二区高清| 久久视频一区| 99精品国产在热久久| 欧美午夜片在线免费观看| 午夜欧美精品久久久久久久| 激情五月综合色婷婷一区二区| 久久免费视频在线观看| 亚洲第一精品电影| 亚洲欧美久久久| 亚洲国产精品99久久久久久久久| 免费视频亚洲| 亚洲制服少妇| 亚洲国产成人精品久久| 亚洲一区免费在线观看| 国产亚洲一区二区在线观看 | 免费观看日韩av| 日韩视频一区二区三区| 久久狠狠亚洲综合| 亚洲精品影院| 国产主播精品| 欧美日韩国产片| 久久久久成人精品| 亚洲少妇中出一区| 欧美黄在线观看| 欧美在线播放| 亚洲视频中文字幕| 亚洲黄色高清| 欧美黄免费看| 欧美黄色成人网| 久久精品国产99精品国产亚洲性色| 亚洲国产精品久久久| 欧美一区二区三区在线观看 | 99国产一区| 欧美成人亚洲成人| 久久色在线观看| 欧美一级日韩一级|