详解C/C++高精度算法的简单实现

详解C/C++高精度算法的简单实现

简介

高精度算法是指在计算机上处理大数(比int、long long等数据类型的范围还要大)时,用特殊的算法进行计算的技术,它可以大大提高程序的精度。本文将详细讲解在C/C++语言中实现高精度算法的方法。

实现思路

实现高精度算法的主要思路是将大数拆分成多个小数,每个小数用数组存储数据,然后借助数组的运算来实现对大数的计算。下面是一些常用的方法:

  1. 将数字转换成数组。例如:数字1937可转换为数组{1,9,3,7}来进行计算。
  2. 实现数组的加减乘除运算。算法的本质是遵循竖式运算法则,一边相加、相减、相乘、相除,一边进位、退位、进位等操作,类似于小学两位数的竖式运算。
  3. 将结果数组转换成数字。例如:数组{1,9,3,7}的值为1937。

实现代码

数字转数组

void numToArr(int num, int* arr, int& len) {
    len = 0;
    while (num) {
        arr[len++] = num % 10;
        num /= 10;
    }
    reverse(arr, arr + len);  // 反转数组
}

数组转数字

int arrToNum(int* arr, int len) {
    int sum = 0;
    for (int i = 0; i < len; i++) {
        sum = sum * 10 + arr[i];
    }
    return sum;
}

高精度加法

void highAdd(int* a, int* b, int* c, int len1, int len2, int& len3) {
    len3 = max(len1, len2);
    int carry = 0;
    for (int i = 0; i < len3; i++) {
        int sum = carry;
        if (i < len1) sum += a[len1 - i - 1];
        if (i < len2) sum += b[len2 - i - 1];
        c[i] = sum % 10;
        carry = sum / 10;
    }
    if (carry != 0) {
        c[len3] = carry;
        len3++;
    }
}

高精度减法

void highSub(int* a, int* b, int* c, int len1, int len2, int& len3) {
    len3 = max(len1, len2);
    int carry = 0;
    for (int i = 0; i < len3; i++) {
        int diff = carry;
        if (i < len1) diff += a[len1 - i - 1];
        if (i < len2) diff -= b[len2 - i - 1];
        if (diff < 0) {
            carry = -1;
            c[i] = diff + 10;
        } else {
            carry = 0;
            c[i] = diff;
        }
    }
    while (len3 > 1 && c[len3 - 1] == 0) len3--; // 去掉高位的0
}

高精度乘法

void highMul(int* a, int* b, int* c, int len1, int len2, int& len3) {
    len3 = len1 + len2;
    memset(c, 0, len3 * sizeof(int)); // 初始化为0
    for (int i = 0; i < len1; i++) {
        for (int j = 0; j < len2; j++) {
            c[i + j] += a[i] * b[j];
            c[i + j + 1] += c[i + j] / 10;
            c[i + j] %= 10;
        }
    }
    while (len3 > 1 && c[len3 - 1] == 0) len3--; // 去掉高位的0
}

高精度除法

void highDiv(int* a, int b, int* c, int len1, int& len3) {
    len3 = len1;
    long long tmp = 0; // 用long long存储计算结果,避免溢出
    for (int i = 0; i < len1; i++) {
        tmp = tmp * 10 + a[i];
        c[i] = tmp / b;
        tmp %= b;
    }
    while (len3 > 1 && c[len3 - 1] == 0) len3--; // 去掉高位的0
}

示例说明

示例1:计算阶乘

// 阶乘计算(利用高精度)
int main() {
    const int MAXN = 1000;
    int a[MAXN], b[MAXN], c[MAXN], d[MAXN], len1, len2, len3, len4;
    int n;
    scanf("%d", &n);
    numToArr(1, a, len1);
    for (int i = 1; i <= n; i++) {
        numToArr(i, b, len2);
        highMul(a, b, c, len1, len2, len3);
        memcpy(a, c, len3 * sizeof(int)); // 等价于 for (int j = 0; j < len3; j++) a[j] = c[j];
        len1 = len3;
    }
    printf("%d! = ", n);
    for (int i = len1 - 1; i >= 0; i--) {
        printf("%d", a[i]);
    }
    printf("\n");
    return 0;
}

输入:n=5.

输出:5!=120.

示例2:计算斐波那契数列

// 斐波那契数列(利用高精度)
int main() {
    const int MAXN = 1000;
    int a[MAXN], b[MAXN], c[MAXN], len1, len2, len3;
    int n;
    scanf("%d", &n);
    numToArr(1, a, len1);
    numToArr(1, b, len2);
    for (int i = 3; i <= n; i++) {
        highAdd(a, b, c, len1, len2, len3);
        memcpy(a, b, len2 * sizeof(int));
        memcpy(b, c, len3 * sizeof(int));
        len1 = len2;
        len2 = len3;
    }
    printf("Fibonacci(%d) = ", n);
    for (int i = len3 - 1; i >= 0; i--) {
        printf("%d", c[i]);
    }
    printf("\n");
    return 0;
}

输入:n=7.

输出:Fibonacci(7)=13.

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解C/C++高精度算法的简单实现 - Python技术站

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

相关文章

  • C++实现的链表类实例

    以下是C++实现的链表类实例的完整攻略。 1. 什么是链表 链表是计算机中常用的一种动态数据结构,它通过节点之间的指针连接,可以比较方便地增、删、改、查数据。链表的节点结构一般包含两部分:数据域和指针域,数据域存储节点所存储的数据,指针域存储下一个节点的位置信息。 2. C++中实现链表类的关键 在C++中,我们可以通过定义一个链表类来实现链表的操作。链表类…

    C 2023年5月23日
    00
  • vue中如何实现复制内容到剪切板详解

    让我们来详细讲解一下“vue中如何实现复制内容到剪贴板”的完整攻略。 第一步:安装依赖 在使用vue实现复制内容到剪贴板之前,需要安装一个剪贴板操作插件clipboard(也可以使用其他类似插件)。 使用npm在项目中安装clipboard插件: npm i clipboard –save 第二步:创建一个指令 在Vue中实现复制内容到剪贴板需要创建一个指…

    C 2023年5月23日
    00
  • springboot项目数据库密码如何加密

    首先,为了保证数据库密码的安全性,我们可以在SpringBoot项目中使用加密算法对数据库密码进行加密。以下是实现步骤: 1.引入依赖 在项目的pom.xml文件中引入Jasypt的依赖: <dependency> <groupId>com.github.ulisesbocchio</groupId> <artifa…

    C 2023年5月23日
    00
  • C++ 中私有继承的作用

    C++ 中的私有继承是一种继承方式,它可以让派生类的对象获得基类的成员,但是这些成员只能在派生类内部访问,从而实现了封装。私有继承的作用有以下几点: 实现代码复用 私有继承可以实现代码的复用。比如有一个基类 Person,其中定义了一些通用的成员变量和函数,而派生类 Teacher 和 Student 都需要使用这些成员。此时可以通过私有继承来避免代码重复。…

    C 2023年5月22日
    00
  • 浅析C语言头文件和库的一些问题

    浅析C语言头文件和库的一些问题 什么是C语言头文件和库? C语言头文件是在程序编写过程中所需的预先编写好的源文件,主要是为了让程序能够调用已经定义好的函数和变量。C库则是一个集成了常用函数的代码集合。这些函数可以在程序中直接调用,而不需要重复编写代码。头文件和库文件的作用是简化程序的编写过程,提高代码的复用性和可维护性。 C语言头文件的分类 系统头文件 系统…

    C 2023年5月23日
    00
  • C++中四种加密算法之AES源代码

    C++中四种加密算法之AES源代码 什么是AES算法 AES是Advanced Encryption Standard的缩写,它是一种对称加密算法,也是目前最常用的加密算法之一。AES算法可以对数据进行加密和解密,同时还能保证数据的完整性和安全性。 AES算法实现步骤 AES算法实现一般包含以下几个步骤: 密钥扩展:对输入密钥进行处理,扩展成多个轮密钥。 初…

    C 2023年5月23日
    00
  • 深入浅出讲解Java比较器及数学常用类

    深入浅出讲解Java比较器及数学常用类 Java比较器 Java中的比较器是用于比较两个对象的大小关系的接口,它定义了一个compare()方法用于比较大小。常用于排序、查找等场景中。 自然排序 自然排序是Java中默认的排序方式,即根据对象所属类型的大小关系进行排序。例如,整数类型按照数值大小进行排序,字符串类型按照字典序进行排序。 public clas…

    C 2023年5月22日
    00
  • python访问纯真IP数据库的代码

    Python访问纯真IP数据库的代码完整攻略 纯真IP数据库是一款用于IP地址查询的软件,可以通过输入一个IP地址来查询对应的区域、省份、城市等信息。在Python中,可以通过访问纯真IP数据库来实现这一功能。下面是实现该功能的完整攻略。 步骤一:下载纯真IP数据库 首先需要从纯真官网下载最新版纯真IP数据库,下载后,解压压缩包,可以得到一个名为“QQWry…

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