c++ - 这种计算大数的方法是如何工作的?

标签 c++ stringstream largenumber

通常,要在 C++ 中处理超出 long long 范围的整数,您必须将它们表示为字符串并以这种方式对它们执行操作。但是,我在互联网上找到了这段代码,它似乎像魔术一样工作。它计算 2 的任意次幂之和(不包括 2^0),即使它不能存储在 long long 中。

#include <iostream>  
#include <cmath>  
#include <iomanip>  
#include <sstream>  
using namespace std;

int main() {
    int n;
    stringstream ss;
    cin >> n;

    ss << fixed << setprecision(0) << pow(2, n + 1) - 2;

    if (n >= 54) {
        string a = ss.str();

        a[a.size() - 1] = ((a[a.size() - 1] - 48) - 2) + 48;

        cout << a;
        return 0;
    }

    cout << ss.str();

}

它是如何工作的?它适用于任何涉及大量的操作吗?如果 n 的值很大(我试过 1024),它只会打印“inf”。这样计算出来的数字范围上限是多少?

下面的部分到底做了什么,为什么要这样做?

a[a.size() - 1] = ((a[a.size() - 1] - 48) - 2) + 48;

最佳答案

Will it work for any operation involving large numbers?

您可以使用 float 执行与使用整数相同的操作。但是每次计算都会出错,而且并不是所有的整数都是可表示的。


What's the upper-limit of the range of numbers that can be calculated this way?

取决于您的处理器使用的 double 浮点类型。

您可以使用 std::numeric_limits<double>::max() 找出最高可表示数.然而,这些高数字的精度非常差。并非所有整数都可以表示到这个数字。连续可表示整数的最大值是std::pow(std::numeric_limits<double>::radix, std::numeric_limits<double>::digits) .


What exactly does the following part do and why does it do it?

a[a.size() - 1] = ((a[a.size() - 1] - 48) - 2) + 48;

这可以简化为

a[a.size() - 1] -= 2;

它只是从最后一位(最低位)减去 2。它依赖于数学事实,即 2 的幂永远不会是 0 或 1 模 10(20 除外),在这种情况下,最后一位数字将成为非数字字符。

它还依赖于 pow(2, n + 1) - 2 == pow(2, n + 1)对于 n >= 54 .该代码假定 float 遵循普遍存在的二进制 IEEE-754 格式,其中 std::pow(std::numeric_limits<double>::radix, std::numeric_limits<double>::digits)std::pow(2, 54) .当n大于等于54,计算结果std::pow(2, 54 + 1)变得如此之大,以至于如果你从中减去一个小数字,如 2,最接近的可表示结果与你开始时的结果相同。计算的精度误差等于较小的操作数!该计算根本无法用 float 执行。这就是为什么后来用数字字符摆弄来修复它的原因。

所有 2 的幂(直到极限)都是可表示的,因此幂计算本身不会有任何精度错误。

关于c++ - 这种计算大数的方法是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42728269/

相关文章:

c++ - 双重释放或损坏错误 - valgrind

c++ - typedef 模板参数成员函数的返回类型

c++ - hh :mm format from a line 中的读取时间

c++ - Qt C++ 在函数模板中使用约束

c++ - cout stringstream 两次以损坏的 cout 结束(最小示例)

c++ - std::stringstream 和 str 方法

c++ - stringstream 字符串后有一个单词的奇怪行为

c++ - 如何乘以大于 uint64 的整数?

c - 指数问题及其 C 表示

以科学记数法返回的 Bash 数字序列?