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
  • Win7旗舰版系统提示应用程序错误代码0xc0000409的故障原因及解决方法

    Win7旗舰版系统提示应用程序错误代码0xc0000409的故障原因及解决方法 问题表现 在 Win7 旗舰版系统中运行某些程序时,可能会遇到应用程序错误,错误代码为 0xc0000409。这时程序会崩溃或无法运行,给用户带来不便。 故障原因 应用程序错误代码 0xc0000409 通常与系统文件中的损坏或错误有关。这可能是由于电脑不正常关机或磁盘损坏等原因…

    C 2023年5月23日
    00
  • java 和 json 对象间转换

    Java和JSON都是广泛使用的编程语言和数据格式,将Java对象转换为JSON对象可以方便地在网络间传输数据。同样,将JSON对象转换为Java对象也可以使其在Java程序中方便使用。下面是Java和JSON对象间转换的完整攻略。 Java对象转换为JSON对象 Java对象转换为JSON对象通常使用第三方库,常用的是Google提供的Gson库和阿里巴巴…

    C 2023年5月23日
    00
  • 一文带你玩转Java异常处理

    一文带你玩转Java异常处理 异常处理概述 Java中的异常处理机制是在程序执行中检测到错误时采取的一种机制,用于保证程序在异常情况下能够进行有序的处理。通常来说,异常可以分为两种:检查异常(Checked Exception)和运行时异常(Runtime Exception)。其中,检查异常必须在代码中进行处理,而运行时异常可以不处理。Java中的异常处理…

    C 2023年5月23日
    00
  • C 程序 递归函数反转给定的数字

    下面是 “C 程序 递归函数反转给定的数字” 的完整使用攻略。 什么是递归函数? 递归函数是一种在函数体内调用自身的函数,这个过程被称为递归。使用递归函数可以编写简洁而优美的代码。 程序简介 此程序旨在使用递归函数反转给定的数字。例如,如果给定数字为 12345,程序将返回 54321。 使用方法 以下是使用此程序的步骤。 1. 确保您已经安装了 C 语言编…

    C 2023年5月9日
    00
  • C++无痛实现日期类的示例代码

    以下是实现C++日期类的完整攻略。 步骤一:设计日期类 首先,我们需要设计日期类的成员变量和成员函数。对于一个日期对象,我们通常需要记录它的年、月、日三个属性。另外,需要实现一些对日期对象的操作方法,例如: 构造函数 获取日期字符串 获取年份 获取月份 获取日 判断是否是闰年 判断是否为合法日期 因此,我们可以设计如下类: class Date { priv…

    C 2023年5月23日
    00
  • 用C语言来实现一个简单的虚拟机

    实现一个简单的虚拟机可以分为以下几个步骤: 设计虚拟机的指令集 编写解析器,将程序代码转化为虚拟机指令 实现虚拟机的内存管理、寄存器、堆栈等功能 实现指令执行器,按照指令集执行代码 具体实现过程如下: 设计虚拟机指令集 首先需要设计虚拟机的指令集,指令集需要包括操作指令、流程控制指令等等。在这里我们设计一个简单的指令集,包括以下几种指令: 指令 功能 pus…

    C 2023年5月23日
    00
  • C#实现Json转DataTable并导出Excel的方法示例

    我将为你详细讲解“C#实现Json转DataTable并导出Excel的方法示例”的完整攻略。以下是该攻略的步骤及示例说明: 步骤一:将Json转为DataTable 使用C#实现Json转DataTable的方法有很多种,比如使用JSON.NET库等。我们以JSON.NET库为例,具体步骤如下: 引用Newtonsoft.Json库: 在Visual St…

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