详解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日

相关文章

  • 将Emacs打造成强大的Python代码编辑工具

    当你选择使用 Emacs 作为 Python 的编辑器时,你会拥有一个非常强大的工具,Emacs 配合一些插件和定制的设置,可以满足你对 Python 编辑器的所有需求。 下面是将 Emacs 打造成强大的 Python 代码编辑工具的攻略: 安装 Python 模式 首先,你需要安装一个称为“Python 模式”的软件包。该软件包提供了一些有用的功能,如代…

    C 2023年5月23日
    00
  • c++ 探讨奶牛生子的问题

    C++ 探讨奶牛生子的问题 问题描述 有 $N$ 只奶牛,每个奶牛的繁殖周期为 $M$ 年,每只奶牛出生后第 $1$ 年不生育,第 $2$ 年起每年生下一只小奶牛,小奶牛出生后第 $1$ 年也不能生育,第 $2$ 年起也可以生下一只小奶牛。假设所有的奶牛都没有死亡,请问 $T$ 年后一共有多少只奶牛? 解题思路 本题可以采用递归或者动态规划的方式进行求解。我…

    C 2023年5月23日
    00
  • 解决vscode下调试c/c++程序一闪而过的问题(Windows)

    下面我将为您详细讲解“解决vscode下调试c/c++程序一闪而过的问题(Windows)”的完整攻略。 问题描述 在使用 Visual Studio Code 进行 C/C++ 的 debug 时,调试控制台会一下子出现,一下子消失,导致无法查看输出结果。这是因为控制台程序执行完成后就立刻退出了,而调试控制台会立刻关闭。这个问题可以通过添加一个 syste…

    C 2023年5月23日
    00
  • C语言编程入门之程序头文件的简要解析

    C语言编程入门之程序头文件的简要解析 什么是头文件 头文件(Header Files)通常是一些包含函数定义、变量声明等的文本文件,其内容可以被多个源文件引用(#include)以便让其内部定义的函数和变量可以在引用这个头文件的源文件中被使用。 头文件的分类 头文件可以分为两类: 1. 系统头文件 系统头文件是由编译器提供的,主要包含一些常用的函数库、数据类…

    C 2023年5月23日
    00
  • 一文搞懂C++中继承的概念与使用

    一文搞懂C++中继承的概念与使用 1. 继承的概念 继承是指在定义一个类时,可以在新的类中直接引用一个已有的父类的属性和行为,新的类称为子类或派生类,已有的类称为父类或基类。 子类会继承父类的公有成员和保护成员,但不会继承父类的私有成员。同时子类可以访问父类的公有成员和保护成员,但无法访问私有成员。 2. 继承的语法 继承语法如下所示: class Chil…

    C 2023年5月22日
    00
  • C++性能剖析教程之循环展开

    下面是关于“C++性能剖析教程之循环展开”的完整攻略: 1. 什么是循环展开 循环展开是一种优化技术,指将循环体语句复制若干次以减少分支和循环的开销,从而提高代码的执行速度。循环展开时需要注意的是展开的次数(即展开因子)应该适量,过大会导致代码膨胀、缓存未命中率增加等问题,影响性能。 循环展开通常需要配合编译命令中的优化选项一起使用,以便在编译时对代码进行优…

    C 2023年5月23日
    00
  • C++单例模式的几种实现方法详解

    C++单例模式的几种实现方法详解 什么是单例模式 单例模式是一种创建型设计模式,它保证一个类只有一个实例,并提供一个全局访问点。 为什么要用单例模式 在实际开发过程中,有些类只需要有一个实例,如果多次实例化,会造成资源浪费。同时保持全局唯一的实例,方便对该实例进行管理和控制,提高程序的可维护性和可拓展性。 实现方法 饿汉式(线程安全) 饿汉式是一种比较常见的…

    C 2023年5月23日
    00
  • 详解C语言编程中预处理器的用法

    详解C语言编程中预处理器的用法 预处理器是C语言中一个非常重要的机制,在代码被编译之前,预处理器会对代码做预处理,将一些宏定义、条件编译、头文件包含等操作替换或者插入到代码中,使得最终编译器拷贝的代码具有期望的形式。下面,我们将通过两个示例来详细讲解预处理器的使用方法。 示例一:头文件包含 C语言中的头文件(.h) 通常包含一些函数的声明、结构体的定义、宏定…

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