高精度算法詳解:從原理到加減乘除的完整實現

文章目錄

  • 一、為什么需要高精度算法
  • 二、高精度算法的數據結構設計
    • 2.1 基礎工具函數
    • 2.2 高精度加法實現
    • 2.3 高精度減法實現
    • 2.4 高精度乘法實現
    • 2.5 高精度除法實現
  • 三、完整測試程序
  • 四、總結

一、為什么需要高精度算法

在編程中,處理極大數值是常見需求,例如:

  • 密碼學中的大數運算(如 RSA 算法中的模冪運算)
  • 科學計算中的高精度數值計算
  • 財務系統中的金額處理
  • 數學競賽中的大數問題求解

C++ 的原生數據類型(如long long)有固定數值范圍限制(通常最大約 9×10^18),無法處理任意大小的整數。高精度算法通過將大數字拆分為多個小單元處理,以字符串或數組存儲每一位數字,模擬手工計算實現各種運算。

二、高精度算法的數據結構設計

在 C++ 中,我們可以通過純函數的方式實現高精度算法,避免使用類封裝,使代碼更加簡潔直接。以下是各個核心功能的實現:

2.1 基礎工具函數

首先實現一些基礎工具函數,用于處理字符串表示的大數:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <stdexcept>// 反轉字符串
std::string reverse(const std::string& s) {return std::string(s.rbegin(), s.rend());
}// 去除前導零
std::string removeLeadingZeros(const std::string& num) {int i = 0;while (i < num.size() - 1 && num[i] == '0') {i++;}return num.substr(i);
}// 判斷是否為負數
bool isNegative(const std::string& num) {return num[0] == '-';
}// 獲取絕對值
std::string getAbs(const std::string& num) {return isNegative(num) ? num.substr(1) : num;
}// 比較兩個非負數字的大小
bool absGreaterOrEqual(const std::string& a, const std::string& b) {if (a.length() != b.length()) {return a.length() > b.length();}return a >= b;
}

2.2 高精度加法實現

高精度加法的核心思路是模擬手工加法運算,從低位到高位逐位相加并處理進位:

// 高精度加法
std::string add(const std::string& a, const std::string& b) {// 處理符號if (isNegative(a) && !isNegative(b)) {return subtract(b, getAbs(a));}if (!isNegative(a) && isNegative(b)) {return subtract(a, getAbs(b));}if (isNegative(a) && isNegative(b)) {return "-" + add(getAbs(a), getAbs(b));}// 兩個正數相加std::string result;int carry = 0;int i = a.size() - 1;int j = b.size() - 1;while (i >= 0 || j >= 0 || carry > 0) {int sum = carry;if (i >= 0) sum += a[i--] - '0';if (j >= 0) sum += b[j--] - '0';result.push_back((sum % 10) + '0');carry = sum / 10;}return removeLeadingZeros(reverse(result));
}

2.3 高精度減法實現

高精度減法比加法更復雜,需要考慮借位和數字大小比較:

// 高精度減法
std::string subtract(const std::string& a, const std::string& b) {// 處理符號if (isNegative(a) && !isNegative(b)) {return "-" + add(getAbs(a), b);}if (!isNegative(a) && isNegative(b)) {return add(a, getAbs(b));}if (isNegative(a) && isNegative(b)) {return subtract(getAbs(b), getAbs(a));}// 兩個正數相減if (!absGreaterOrEqual(a, b)) {return "-" + subtract(b, a);}std::string result;int borrow = 0;int i = a.size() - 1;int j = b.size() - 1;while (i >= 0) {int diff = (a[i] - '0') - borrow;if (j >= 0) diff -= (b[j] - '0');if (diff < 0) {diff += 10;borrow = 1;} else {borrow = 0;}result.push_back(diff + '0');i--;j--;}return removeLeadingZeros(reverse(result));
}

2.4 高精度乘法實現

高精度乘法通常采用豎式乘法的思路,時間復雜度為 O (n2):

// 高精度乘法
std::string multiply(const std::string& a, const std::string& b) {// 處理零的情況if (a == "0" || b == "0") {return "0";}// 處理符號bool isNegative = (isNegative(a) && !isNegative(b)) || (!isNegative(a) && isNegative(b));std::string absA = getAbs(a);std::string absB = getAbs(b);// 結果數組,長度為兩數位數之和std::vector<int> result(absA.size() + absB.size(), 0);// 豎式乘法核心邏輯for (int i = absA.size() - 1; i >= 0; i--) {for (int j = absB.size() - 1; j >= 0; j--) {int product = (absA[i] - '0') * (absB[j] - '0');int sum = product + result[i + j + 1];result[i + j + 1] = sum % 10;result[i + j] += sum / 10;}}// 轉換結果數組為字符串std::string resultStr;for (int num : result) {if (!(resultStr.empty() && num == 0)) {resultStr.push_back(num + '0');}}return (isNegative ? "-" : "") + resultStr;
}

2.5 高精度除法實現

高精度除法是最復雜的運算,這里采用試商法實現:

// 高精度除法
std::string divide(const std::string& a, const std::string& b) {// 處理除數為零的情況if (b == "0") {throw std::runtime_error("Division by zero");}// 處理零的情況if (a == "0") {return "0";}// 處理符號bool isNegative = (isNegative(a) && !isNegative(b)) || (!isNegative(a) && isNegative(b));std::string absA = getAbs(a);std::string absB = getAbs(b);// 處理被除數小于除數的情況if (!absGreaterOrEqual(absA, absB)) {return "0";}// 試商法核心邏輯std::string quotient;std::string remainder;for (char c : absA) {remainder += c;remainder = removeLeadingZeros(remainder);int count = 0;while (absGreaterOrEqual(remainder, absB)) {remainder = subtract(remainder, absB);count++;}quotient += std::to_string(count);}quotient = removeLeadingZeros(quotient);return (isNegative ? "-" : "") + quotient;
}// 高精度取模
std::string mod(const std::string& a, const std::string& b) {if (b == "0") {throw std::runtime_error("Modulo by zero");}if (a == "0") {return "0";}bool isNegative = isNegative(a);std::string absA = getAbs(a);std::string absB = getAbs(b);if (!absGreaterOrEqual(absA, absB)) {return a;}std::string quotient = divide(absA, absB);std::string product = multiply(quotient, absB);std::string remainder = subtract(absA, product);return (isNegative ? "-" : "") + remainder;
}

三、完整測試程序

下面是一個完整的測試程序,展示如何使用上述高精度算法:

// 測試程序
int main() {try {// 測試加法std::cout << "加法測試: 12345 + 67890 = " << add("12345", "67890") << std::endl;// 測試減法std::cout << "減法測試: 98765 - 12345 = " << subtract("98765", "12345") << std::endl;// 測試乘法std::cout << "乘法測試: 1234 * 5678 = " << multiply("1234", "5678") << std::endl;// 測試除法std::cout << "除法測試: 123456789 / 12345 = " << divide("123456789", "12345") << std::endl;// 測試取模std::cout << "取模測試: 123456789 % 12345 = " << mod("123456789", "12345") << std::endl;// 測試負數運算std::cout << "負數測試:" << std::endl;std::cout << "-123 + 456 = " << add("-123", "456") << std::endl;std::cout << "123 - (-456) = " << subtract("123", "-456") << std::endl;std::cout << "-123 * (-456) = " << multiply("-123", "-456") << std::endl;std::cout << "-12345 / 67 = " << divide("-12345", "67") << std::endl;} catch (const std::exception& e) {std::cerr << "錯誤: " << e.what() << std::endl;return 1;}return 0;
}

四、總結

高精度算法是處理大數運算的基礎,其核心在于:

  • 將大數字拆分為小單元處理
  • 模擬手工計算過程(進位、借位、試商等)
  • 合理處理符號和邊界情況

理解高精度算法不僅有助于解決實際問題,還能加深對數字運算本質的理解。在密碼學、科學計算等領域,高精度算法更是不可或缺的基礎工具。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/83620.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/83620.shtml
英文地址,請注明出處:http://en.pswp.cn/web/83620.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

排序--計數排序

一,引言 計數排序是一種針對整數數據的高效排序算法。其主要流程可分為三個步驟&#xff1a;首先計算整數數據的數值范圍&#xff1b;接著按大小順序統計各數值的出現次數&#xff1b;最后根據統計結果輸出排序后的數據序列。 二,求最值 遍歷現有數據&#xff0c;獲取最大值…

Kubernetes安全機制深度解析(四):動態準入控制和Webhook

#作者&#xff1a;程宏斌 文章目錄 動態準入控制什么是準入 Webhook&#xff1f; 嘗試準入Webhook先決條件編寫一個準入 Webhook 服務器部署準入 Webhook 服務即時配置準入 Webhook對 API 服務器進行身份認證 Webhook 請求與響應Webhook 配置匹配請求-規則匹配請求&#xff1a…

WDK 10.0.19041.685,可在32位win7 sp1系統下搭配vs2019使用,可以編譯出xp驅動。

(14)[驅動開發]配置環境 VS2019 WDK10 寫 xp驅動 (14)[驅動開發]配置環境 VS2019 WDK10 寫 xp驅動_microsoft visual 2019 wdk-CSDN博客文章瀏覽閱讀3k次&#xff0c;點贊8次&#xff0c;收藏17次。本文介紹了如何在VS2019環境下安裝和配置Windows Driver Kit(WDK)&#xff0…

論壇系統自動化測試

1、項目背景與測試目標 系統定位 論壇系統作為典型的高并發Web應用&#xff0c;需支持用戶注冊、登錄、發帖、評論、私信及個人中心管理等核心功能&#xff0c;是用戶公開交流與信息共享的核心平臺。其穩定性與響應效率直接影響用戶體驗及平臺活躍度。 測試必要性 功能可靠性&…

ChipWhisperer教程(一)

一、ChipWhisperer介紹 ChipWhisperer 是一個完整的開源工具鏈&#xff0c;用于學習嵌入式設備上的側信道攻擊并驗證這些設備的側信道抗性。ChipWhisperer主要用于功耗分析&#xff0c;利用設備功耗泄露的信息進行攻擊&#xff0c;也可用于故障攻擊&#xff08;電壓和時鐘毛刺…

【持續更新】計算機網絡試題

問題1 請簡要說明TCP/IP協議棧的四層結構&#xff0c;并分別舉出每一層出現的典型協議或應用。 答案 應用層&#xff1a;ping,telnet,dns 傳輸層&#xff1a;tcp,udp 網絡層&#xff1a;ip,icmp 數據鏈路層&#xff1a;arp,rarp 問題2 下列協議或應用分別屬于TCP/IP協議…

短劇系統開發:打造高效、創新的短視頻娛樂平臺 - 從0到1的完整解決方案

一、短劇市場迎來爆發式增長 - 不容錯過的萬億級藍海 隨著5G技術的普及和移動互聯網的深度滲透&#xff0c;短劇市場正在經歷前所未有的爆發式增長。根據權威機構艾瑞咨詢最新發布的《2023年中國網絡短劇行業發展報告》顯示&#xff1a; 市場規模&#xff1a;2023年中國短劇市…

ChipWhisperer教程(三)

——CW305目標板的波形采集 一、目標板介紹 CW305 是一款獨立的 FPGA 目標板&#xff0c;搭載的FPGA芯片為Xilinx Artix-7系列。 它具有與 FPGA 通信的 USB 接口、為 FPGA 提供時鐘的外部 PLL、編程 VCC-INT 電源以及用于故障注入環境的二極管保護。 CW305 電路板有多種配置&…

django中如何解析content-type=application/json的請求

django中如何解析content-typeapplication/json的請求 本文由「大千AI助手」原創發布&#xff0c;專注用真話講AI&#xff0c;回歸技術本質。拒絕神話或妖魔化。搜索「大千AI助手」關注我&#xff0c;一起撕掉過度包裝&#xff0c;學習真實的AI技術&#xff01; 往期文章回顧: …

Chainlink VRF 深度解析與實戰

背景 在區塊鏈的去中心化應用中&#xff0c;隨機性是一個常見但難以實現的需求。例如&#xff0c;區塊鏈游戲需要隨機決定戰斗結果&#xff0c;NFT 項目需要隨機分配稀有屬性&#xff0c;去中心化抽獎需要公平選擇獲獎者。然而&#xff0c;傳統的鏈上隨機數生成方法&#xff0…

7. TypeScript接口

TypeScript 中的接口&#xff08;Interfaces&#xff09;用于定義對象的結構。它們允許開發者指定一個對象應具有哪些屬性以及這些屬性的類型。接口有助于確保對象遵循特定的結構&#xff0c;從而在整個應用中提供一致性&#xff0c;并提升代碼的可維護性。 一、認識接口 Typ…

UE 新版渲染器輸出視頻

安裝包解壓到C盤 打開UE插件 Movie Render Queue 進入UE引擎在項目設置找到 libx264 aac mp4 影片渲染隊列調用出 命令行編碼器安裝包路徑&#xff0c;序列輸出路徑&#xff0c;定序器不能有中文

基于用戶的協同過濾推薦算法實現(Java電商平臺)

在電商平臺中&#xff0c;基于用戶的協同過濾推薦算法是一種常見的推薦系統方法。它通過分析用戶之間的相似性來推薦商品。以下是一個簡單的實現思路和示例代碼&#xff0c;使用Java語言。 實現思路 數據準備&#xff1a;收集用戶的評分數據&#xff0c;通常以用戶-商品評分矩…

LeetCode - 904. 水果成籃

題目 904. 水果成籃 - 力扣&#xff08;LeetCode&#xff09; 思路 題目本質 你有一個整數數組&#xff0c;每個元素代表一種水果。你只能用兩個籃子&#xff0c;每個籃子只能裝一種水果。你要在數組中找一個最長的連續子數組&#xff0c;這個子數組里最多只包含兩種不同的…

發現 Kotlin MultiPlatform 的一點小變化

最近發現 Kotlin 官方已經開始首推 Idea 的社區版的 KMP 插件了. 以前有網頁創建 KMP 的項目的文檔也消失了. 雖然有 Android Studio 的選項. 但是卻不是在默認的位置上了. 足以說明官方是有意想讓大家直接使用 Idea 社區版或者專業版 所以我直接在社區版上安裝 KMP 插件. 嘗試…

【Photoshop】金屬字體制作

新建一個空白項目&#xff0c;選擇橫排文字工具&#xff0c;輸入想要的文件建立文字圖層 選擇橫排文字工具選擇出文字內容&#xff0c;在通知欄出點擊’拾色器‘&#xff0c;設置好需要的文字顏色 圖層面板右下角點擊‘添加圖層樣式’&#xff0c;選擇斜面和浮雕 樣式設置為內斜…

centos 7.9 升級ssh版本 7.4p1 升級到 8.2p1

centos 7.9 升級ssh版本 7.4p1 升級到 8.2p1 1、安裝包下載2、安裝telnet3、安裝openssl-OpenSSL_1_1_1f.tar.gz4、安裝openssh-8.2p1.tar.gz5、修改ssh服務的相關配置文件6、確定可以ssh連接服務器后&#xff0c;卸載telnet&#xff0c;因為telnet不安全 本文是離線環境下升級…

stm32---dma串口發送+fifo隊列框架

之前分享了一個關于gd32的fifo框架&#xff0c;這次就用stm32仿照寫一個&#xff0c;其實幾乎一樣&#xff0c;這次說的更詳細點&#xff0c;我全文都寫上了注釋&#xff0c;大家直接cv模仿我的調用方式即可 uasrt.c #include "stm32f10x.h" // D…

【生產就曲篇】讓應用可觀測:Actuator監控端點與日志最佳實踐

摘要 本文是《Spring Boot 實戰派》系列的終章&#xff0c;我們將探討如何讓應用真正達到**“生產就緒” (Production-Ready)** 的標準。文章的核心是可觀測性 (Observability)&#xff0c;即從外部了解一個系統內部運行狀態的能力。 我們將深度挖掘 Spring Boot Actuator 的…

操作系統知識(1)

操作系統的分類總結 1、批處理操作系統:單道批處理和多道批處理(主機與外設可并行) 2、分時操作系統:一個計算機系統與多個終端設備連接。將CPU的工作時間劃分為許多很短的時間片&#xff0c;輪流為各個終端的用戶服務。 3、實時操作系統:實時是指計算機對于外來信息能夠以足…