成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

看了就會的大整數乘法運算與分治算法

開發 前端 算法
在數據加密處理中有很多復雜的加密算法,這些加密算法往往會用到很多超大的整數運算。

[[352004]]

在數據加密處理中有很多復雜的加密算法,這些加密算法往往會用到很多超大的整數運算。不過,程序設計語言對數據的大小會有一定的限制,數據太大就會出現數據溢出的情況,這是無法進行大整型數據運算的。本文將和大家一起學習如何實現大整數的數據運算,本文代碼我們使用C++實現。

普通乘數運算

對于乘數運算有一種比較簡單較為容易理解的方法,我們可以利用小學時期學的列豎式的計算方法進行乘法運算。

列豎式乘法運算

參考上圖中的列豎式計算方法,我們進行代碼實現。

  1. #include <iostream> 
  2. #include <string> 
  3. #include <stdlib.h> 
  4. #include <vector> 
  5. #include <cstring> 
  6. #include <algorithm> 
  7.  
  8. std::string multiply(std::string a, std::string b) 
  9.     std::string result = ""
  10.     int row = b.size(); 
  11.     int col = a.size() + 1; 
  12.     int tmp[row][col]; 
  13.     memset(tmp,0, sizeof(int)*row*col); 
  14.      
  15.     reverse(a.begin(),a.end()); 
  16.     reverse(b.begin(),b.end()); 
  17.      
  18.     for(int i = 0; i < b.size(); i++) 
  19.     { 
  20.         for(int j = 0; j < a.size(); j++) 
  21.         { 
  22.             std::string bit_a = std::string(1, a.at(j)); 
  23.             std::string bit_b = std::string(1, b.at(i)); 
  24.              
  25.             tmp[i][j] += std::stoi(bit_a) * std::stoi(bit_b); 
  26.          
  27.             tmp[i][j+1] = tmp[i][j] / 10; 
  28.             tmp[i][j] %= 10; 
  29.  
  30.         } 
  31.  
  32.     } 
  33.  
  34.     int N =  a.size() + b.size(); 
  35.     int sum[N]; 
  36.     memset(sum, 0, sizeof(int)*N); 
  37.      
  38.     for(int n = 0; n < N; n++) 
  39.     { 
  40.         int i = 0; 
  41.         int j = n; 
  42.          
  43.         while (i <= n && j >= 0 ) 
  44.         { 
  45.             if(i < row && j < col) 
  46.             { 
  47.                 sum[n] += tmp[i][j]; 
  48.             } 
  49.              
  50.             i++; 
  51.             j--; 
  52.         } 
  53.  
  54.         if( n+1 < N ) 
  55.         { 
  56.             sum[n+1] = sum[n] / 10; 
  57.             sum[n] %= 10; 
  58.         } 
  59.  
  60.     } 
  61.  
  62.     bool zeroStartFlag = true
  63.     for (int i = N-1; i >= 0; i--) 
  64.     { 
  65.         if(sum[i]==0 && zeroStartFlag) 
  66.         { 
  67.             continue
  68.         } 
  69.          
  70.         zeroStartFlag = false
  71.         result.append(std::to_string(sum[i])); 
  72.     } 
  73.      
  74.     return result; 
  75.  
  76.  
  77. int main() 
  78.     std::string a = "3456"
  79.     std::string b = "1234"
  80.  
  81.     std::string result = multiply(a, b);     
  82.     std::cout << a << " * " << b << " = " << result <<std::endl; 
  83.      
  84.     return 0; 

為了方便我們先將各個乘數做了翻轉處理,最后需要再將結果翻轉回來。在運算過程中用來存放乘法運算結果的數組,我們沒有進行移位處理同列相加,而是對角線相加,這樣可以減少空間和運算步驟。上面的代碼運行結果如下所示。

運行結果

因為字符串的長度沒有特別的限制,所以上面的算法可以適用大整數運算。

分治算法

雖然上面的列豎式的方法可以很好的解決大整數乘法的問題,但是我們還用一種更加高效的方法可以選擇,這就是分治(Divide and Conquer)算法。它是一種非常重要的算法,可以應用到很多領域,比如快速排序,二分搜索等。從算法的名字我們可以看出它是將大的問題拆分進行細化,由大變小,先將小的問題解決,最終將這個問題解決,所以叫Divide and Conquer。在這里我們可以通過這種方法將大整數進行拆分,拆分成一個個可以通過程序語言直接進行運算的小整進行計算,最后求得到大整數的值。

假設有兩個大整數,我們設為a(大小為n位)和b(大小為m位),這里我們將使用二分法對數據進行拆分,這兩個整數我們可以分解為:

則,

令,

根據上面公式里,我們可以將a*b分解為四個小的整數的乘法,即z3,z2,z1,z0四個表達式。如果分解出來的乘法數值還是很大,還可以按照同樣的方法進行拆解直到拆解成較小的數值乘法,直到計算機程序語言可以直接運算。

比如,上面的3456和1234相乘,參考下圖通過二分法逐級對整數進行拆分,我們將兩個整數拆分到一位整數進行運算。

3456和1234拆分步驟圖

下面我們看一下分治算法的代碼實現,這里我們使用遞歸的方法。

  1. #include <iostream> 
  2. #include <string> 
  3. #include <stdlib.h> 
  4. #include <vector> 
  5. #include <cstring> 
  6. #include <algorithm> 
  7. #include <cmath> 
  8.  
  9. std::string add(std::string a, std::string b) 
  10.     int N = std::max(a.size(), b.size()); 
  11.     int sum[N]; 
  12.     memset(sum, 0, sizeof(int)*N); 
  13.      
  14.     reverse(a.begin(),a.end()); 
  15.     reverse(b.begin(),b.end()); 
  16.  
  17.     for(int i = 0; i< N; i++) 
  18.     { 
  19.         int bit_a = 0; 
  20.         int bit_b = 0; 
  21.         if(i < a.size()) bit_a = std::stoi(std::string(1, a.at(i))); 
  22.         if(i < b.size()) bit_b = std::stoi(std::string(1, b.at(i))); 
  23.  
  24.         sum[i] += (bit_a + bit_b); 
  25.  
  26.         if(i < N-1 && sum[i]>9) 
  27.         { 
  28.             sum[i+1] = sum[i] / 10; 
  29.             sum[i] %=10; 
  30.         } 
  31.     } 
  32.  
  33.     std::string result=""
  34.     bool zeroStartFlag = true
  35.     for (int i = N-1; i >= 0; i--) 
  36.     { 
  37.         if(sum[i]==0 && zeroStartFlag) 
  38.         { 
  39.             continue
  40.         } 
  41.          
  42.         zeroStartFlag = false
  43.         result.append(std::to_string(sum[i])); 
  44.     } 
  45.  
  46.  
  47.     return result; 
  48.  
  49. std::string divideAndConquer(std::string a, std::string b) 
  50.     if( a.size() < 2 && b.size() < 2)  
  51.     { 
  52.         return std::to_string(std::stoi(a) * std::stoi(b)); 
  53.     } 
  54.      
  55.     int n = a.size(); 
  56.     int m = b.size(); 
  57.      
  58.     int halfN = n/2; 
  59.     int halfM = m/2; 
  60.  
  61.     std::string a0 = "0"
  62.     std::string a1 = "0"
  63.     if(a.size() > halfN && halfN > 0) 
  64.     { 
  65.         a1 = a.substr(0, halfN); 
  66.         a0 = a.substr(halfN, a.size() - halfN); 
  67.     } 
  68.     else 
  69.     { 
  70.         a1 = "0"
  71.         a0 = a; 
  72.     } 
  73.      
  74.     std::string b0 = "0"
  75.     std::string b1 = "0"
  76.     if(b.size() > halfM && halfM > 0) 
  77.     { 
  78.         b1 = b.substr(0, halfM); 
  79.         b0 = b.substr(halfM, b.size() - halfM); 
  80.  
  81.     } 
  82.     else 
  83.     { 
  84.         b1 = "0"
  85.         b0 = b; 
  86.     } 
  87.  
  88.     std::string a1b1 = divideAndConquer(a1, b1); 
  89.     std::string a0b0 = divideAndConquer(a0, b0); 
  90.     std::string a1b0 = divideAndConquer(a1, b0); 
  91.     std::string a0b1 = divideAndConquer(a0, b1); 
  92.      
  93.     a1b1.append((n - halfN) + (m - halfM), '0'); 
  94.     a1b0.append(n - halfN, '0'); 
  95.     a0b1.append(m - halfM, '0'); 
  96.  
  97.     std::string result = ""
  98.     result = add(a1b1, a1b0); 
  99.     result = add(result, a0b1); 
  100.     result = add(result, a0b0); 
  101.  
  102.     return result; 
  103.  
  104. int main() 
  105.     std::string a = "3456"
  106.     std::string b = "1234"
  107.  
  108.     std::cout << a << " * " << b << " = " << divideAndConquer(a, b) << std::endl;  
  109.  
  110.     return 0; 

程序的運行結果如下:

分治算法運行結果

本文轉載自微信公眾號「Will的大食堂」,可以通過以下二維碼關注。轉載本文請聯系Will的大食堂公眾號。

 

責任編輯:武曉燕 來源: Will的大食堂
相關推薦

2022-07-12 08:27:18

Zadig開源

2021-04-19 11:40:15

瀏覽器路徑

2020-06-05 18:09:14

TomcatWeb應用服務器

2021-05-12 09:07:09

Java數據結構算法

2023-01-08 23:06:14

css3d變換

2020-10-20 08:14:08

算法與數據結構

2020-12-02 09:36:20

算法分支思想

2021-03-24 15:10:11

算法科學技術

2024-12-30 00:01:00

多模態大模型Python

2019-05-28 14:33:07

Javascript運算符前端

2024-03-11 12:21:07

模型數據

2017-09-18 09:26:51

PHP代碼大整數

2011-06-08 17:45:54

AOFAX傳真機

2021-07-16 10:46:52

PythonNumpy數據溢出

2020-11-09 10:01:29

Python乘法位運算

2025-04-08 01:11:00

算法FFT排序

2024-10-22 15:41:47

NumPyPython

2020-08-12 07:59:15

Long類型

2012-02-22 14:12:08

算法
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 毛片毛片毛片毛片毛片 | 亚洲高清视频一区二区 | 午夜影院在线免费观看视频 | 久久精品亚洲精品国产欧美 | 国产精品视频一二三区 | 男人的天堂一级片 | 色爱综合网 | 欧美激情一区二区 | 精品欧美久久 | 国产精品欧美一区二区三区 | 精品在线| 一区二区三区精品视频 | 成人免费在线视频 | 日韩视频区 | 日韩中文字幕在线免费 | 亚洲中午字幕 | 久久久久久久综合 | 色本道 | 日本免费在线看 | 91在线看| 99久热在线精品视频观看 | 久久男人天堂 | 欧美精品久久久 | 亚洲理论在线观看电影 | 国产精品视频偷伦精品视频 | 亚洲精品一区中文字幕乱码 | 日本不卡在线观看 | 国产福利在线看 | 亚洲精品欧美精品 | 欧美一级视频免费看 | av日韩精品| 成人精品福利 | 日韩精品一区二区三区视频播放 | 久久精品亚洲精品国产欧美kt∨ | 成人在线精品 | 全免费a级毛片免费看视频免 | 国产三区精品 | 中文字幕精品一区 | 久久精品国产一区二区电影 | 国产一级片网站 | 9191成人精品久久 |