C/C++高精度(加减乘除)算法的实现

C/C++高精度算法实现方法

背景

C/C++内置的整型数据类型(int、long等)的取值范围都有限制,例如int类型的取值范围为-2147483648~2147483647,这个取值范围对于绝大部分的算法应用是足够的。但是有时候我们需要进行很大数的计算,此时常规的整型数据类型就无能为力了。这时我们需要实现高精度算法来解决这个问题。

实现

高精度算法的实现思路是将一个整数拆分成很多位的数字进行计算。因为C/C++语言对于数值的处理是以原码的形式存在的,所以我们需要先将数字进行存储,通常方式可以使用字符串来存储数字。然后再对每一位进行计算。

  1. 加法实现

高精度加法的实现思路是把两个数字(用字符串存储)从右向左依次相加,同时在每一位上处理进位的情况。

以C++代码实现如下:

string add(string a, string b) {
    // 确定a和b的长度
    int lena = a.size();
    int lenb = b.size();
    // 将a和b的长度变成一致
    if(lena < lenb) {
        a = string(lenb - lena, '0') + a;
    }
    else {
        b = string(lena - lenb, '0') + b;
    }
    // 定义一个存储结果的字符串
    string res = "";
    // 定义一个进位标记,初值为0
    int carry = 0;
    // 从右向左遍历a和b
    for(int i = a.size() - 1; i >= 0; i--) {
        // 记录当前位的结果
        int tmp = a[i] - '0' + b[i] - '0' + carry;
        // 处理进位
        if(tmp >= 10) {
            tmp = tmp - 10;
            carry = 1;
        }
        else {
            carry = 0;
        }
        // 将当前位的结果转化为字符并拼接到res后面
        res = char(tmp + '0') + res;
    }
    // 处理最高位的进位
    if(carry == 1) {
        res = "1" + res;
    }
    return res;
}

示例:

输入:
a = "12345678888888888888888", b = "87654321111111111111111"
输出:
"a + b = 99999999999999999999999"
  1. 减法实现

高精度减法的实现思路是把两个数字(用字符串存储)从右向左依次相减,同时在每一位上处理借位的情况。

以C++代码实现如下:

string sub(string a, string b) {
    // 确定a和b的长度
    int lena = a.size();
    int lenb = b.size();
    // 将a和b的长度变成一致
    if(lena < lenb) {
        a = string(lenb - lena, '0') + a;
    }
    else {
        b = string(lena - lenb, '0') + b;
    }
    // 定义一个存储结果的字符串
    string res = "";
    // 定义一个借位标记,初值为0
    int borrow = 0;
    // 从右向左遍历a和b
    for(int i = a.size() - 1; i >= 0; i--) {
        // 记录当前位的结果
        int tmp = a[i] - b[i] - borrow;
        // 处理借位
        if(tmp < 0) {
            tmp = tmp + 10;
            borrow = 1;
        }
        else {
            borrow = 0;
        }
        // 将当前位的结果转化为字符并拼接到res后面
        res = char(tmp + '0') + res;
    }
    // 去掉结果前导的0
    while(res.size() > 1 && res[0] == '0') {
        res.erase(res.begin());
    }
    return res;
}

示例:

输入:
a = "12345678888888888888888", b = "87654321111111111111111"
输出:
"a - b = 358135777777777777777"

输入: 
a = "10000000000", b = "9999999998"
输出:
"a - b = 2"
  1. 乘法实现

高精度乘法的实现思路是将两个数字从低位到高位分别相乘,并且将结果进行累加,同时在每一位上处理进位的情况。

以C++代码实现如下:

string mul(string a, string b) {
    // 确定a和b的长度
    int lena = a.size();
    int lenb = b.size();
    // 定义一个长度为lena+lenb的数组,初值均为0
    vector<int> c(lena + lenb, 0);
    // 从右向左遍历a和b
    for(int i = lena - 1; i >= 0; i--) {
        for(int j = lenb - 1; j >= 0; j--) {
            // 计算当前位的结果并累加
            int tmp = (a[i] - '0') * (b[j] - '0');
            c[i + j] += tmp % 10;
            c[i + j + 1] += tmp / 10;
        }
    }
    // 处理进位
    for(int i = lena + lenb - 1; i > 0; i--) {
        c[i - 1] += c[i] / 10;
        c[i] %= 10;
    }
    // 将数字转换成字符串
    string res = "";
    for(int i = 0; i < lena + lenb; i++) {
        res += char(c[i] + '0');
    }
    // 去掉结果前导的0
    while(res.size() > 1 && res[0] == '0') {
        res.erase(res.begin());
    }
    return res;
}

示例:

输入:
a = "3141592653589793238462643383279502884197169399375105820974944592", b = "2718281828459045235360287471352662497757247093699959574966967627"
输出:
"a * b = 85397342226735670654635508695465744950348885357651149662156214958094829692774015306456435171075655103989388185261594431010553162683782209088885183430857083831676959258194215804621791426607152452534528352428316383551154792000582925623300905832561334310302899241416157204237264096195863152023724147832970239182246213377282028626077162163681257860606926376734359426968205904903894678404735676246505432122003775"
  1. 除法实现

高精度除法的实现思路是将被除数和除数从高位到低位进行判断,每一位上的计算除法和余数。这里通过类似手算竖式的方式实现。

以C++代码实现如下:

// 高精度除法,返回a/b的结果
string div(string a, string b) {
    string res = "";    // 存储结果的字符串
    string r = "";      // 存储余数的字符串
    for(int i = 0; i < a.size(); i++) {
        r += a[i];      // 逐渐添加数字,计算当前的余数
        int d = 0;      // 当前位商的值
        // 如果当前的余数长度小于除数的长度,则直接添加0
        if(r.size() < b.size()) {
            res += '0';
        }
        else {
            // 在余数大于等于除数的情况下,逐渐减掉除数
            while(r >= b) {
                r = sub(r, b);  // 减去除数(使用高精减法)
                d++;
            }
            // 将当前的商添加到结果字符串当中
            res += char(d + '0');
        }
    }
    // 去掉结果前导的0
    while(res.size() > 1 && res[0] == '0') {
        res.erase(res.begin());
    }
    return res;
}

示例:

输入:
a = "2147483648", b = "123456789"
输出:
"a / b = 17"

输入:
a = "1000000000000000000000", b = "123456789"
输出:
"a / b = 8100000000"

总结

高精度算法是解决基础算法的常见问题之一。本文介绍了高精度算法的C/C++实现方法,并且提供了加法、减法、乘法、除法的示例程序,希望对读者有所帮助。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C/C++高精度(加减乘除)算法的实现 - Python技术站

(0)
上一篇 2023年5月23日
下一篇 2023年5月23日

相关文章

  • C++类和对象深入探索之分文件编写点和圆的关系详解

    首先,为了讲解“C++类和对象深入探索之分文件编写点和圆的关系详解”,我们需要先了解C++中的类和对象是什么,以及如何实现类和对象。 类和对象的概念 在C++中,类是一种可以封装数据和方法的数据类型,可以理解为是对现实生活中某一个事物的抽象,例如现实生活中的汽车可以看作是一个类。而对象是类的一个实例化,是类的具体个体化,例如现实生活中的一辆特定品牌的汽车可以…

    C 2023年5月22日
    00
  • C++递归算法实例代码

    C++递归算法是指函数内部调用自身的方法,用来解决复杂的问题。在编写递归算法时,首先需要确定递归基(即结束条件),然后通过递归调用不断缩小问题规模,直到达到递归基结束递归。下面是C++递归算法的实例代码: 一、递归实现斐波那契数列 斐波那契数列是指数列中每个数都是前两个数的和。下面是用递归实现斐波那契数列的代码: int fibonacci(int n) {…

    C 2023年5月22日
    00
  • C语言选择排序算法及实例代码

    C语言选择排序算法及实例代码 算法介绍 选择排序算法是一种简单的排序算法,它的基本思想是依次遍历数组元素,每次找到剩余元素中的最小值,将其放到未排序部分的最前面。它的时间复杂度为O(n²),空间复杂度为O(1),适用于各种数据规模。 选择排序算法的流程如下: 在未排序序列中找到最小元素,存放到排序序列的起始位置 再从剩余未排序元素中继续寻找最小元素,然后放到…

    C 2023年5月30日
    00
  • C++ 面试题翻译电话号码实例代码

    C++ 面试题翻译电话号码实例代码题目要求实现一个能够将电话号码翻译成字母的程序。具体来讲,即是将类似于”23″这样的数字字符串翻译成所有可能的字母组合,其中 ‘2’ 可以代表 ‘a’, ‘b’, ‘c’, ‘3’ 可以代表 ‘d’, ‘e’, ‘f’,以此类推,直到 ‘9’ 可以代表 ‘w’, ‘x’, ‘y’, ‘z’。对于一个包含多个数字的字符串,其可…

    C 2023年5月24日
    00
  • JS实现合并json对象的方法

    JS实现合并json对象的方法共有多种,以下是其中的几种常用方法的详细讲解: 方法一:使用Object.assign Object.assign() 方法用于将一个或多个来源对象的可枚举属性拷贝到目标对象中,然后返回目标对象。该方法的基本语法如下: Object.assign(target, …sources) 其中,target 表示目标对象,sour…

    C 2023年5月23日
    00
  • JavaScript ES6解构运算符的理解和运用

    JavaScript ES6解构运算符的理解和运用 简介 ES6引入了解构运算符(destructuring assignment),该运算符提供了一种灵活且直观的方式来进行数组或对象的解构赋值,能够大大简化代码的书写和编写效率。本文将深入探讨ES6解构运算符的理解和运用。 数组解构 通过解构运算符可以将数组中的元素解构出来,并赋值给多个变量。下面是一个例子…

    C 2023年5月23日
    00
  • sqlmap之os shell图文详细解析

    让我来详细讲解“sqlmap之os shell图文详细解析”的完整攻略。 SQLMap之OS Shell图文详细解析 什么是SQLMap SQLMap是一个用于检测和利用SQL注入漏洞的开源工具,可以自动化地进行注入测试,并且提供了多种手段来发现和利用漏洞,是渗透测试中非常实用的工具之一。SQLMap完全基于Python开发,支持Linux和Windows操…

    C 2023年5月23日
    00
  • jQuery调取jSon数据并展示的方法

    下面我将为您详细讲解“jQuery调取jSon数据并展示的方法”的完整攻略。 前置知识 在学习jQuery调取jSon数据并展示的方法前,需要先了解jSon的基本语法和jQuery的基础知识。 步骤说明 下面是调取jSon数据并展示的方法: 定义数据源 首先,需要定义jSon数据源,这里我们可以使用一个本地的jSon文件,或者通过Ajax请求获取一个远程服务…

    C 2023年5月23日
    00
合作推广
合作推广
分享本页
返回顶部