Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/134.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 大数的有效幂运算(我说的是Googols)_C++_Biginteger_Bignum_Exponentiation - Fatal编程技术网

C++ 大数的有效幂运算(我说的是Googols)

C++ 大数的有效幂运算(我说的是Googols),c++,biginteger,bignum,exponentiation,C++,Biginteger,Bignum,Exponentiation,我正在解决一个简单的组合问题,它的解是2^n-1 唯一的问题是你根本不需要做任何乘法运算。2^n-1只是1在代码中应用此方法的最简单方法是以最直接的方式(递归)应用它。它适用于任何数字a,而不仅仅是2,因此我编写了将a作为参数的代码,以使其更有趣: MyBigInt pow(MyBigInt a, int p) { if (!p) return MyBigInt.One; MyBigInt halfPower = pow(a, p/2); MyBigInt res = (

我正在解决一个简单的组合问题,它的解是2^n-1


唯一的问题是你根本不需要做任何乘法运算。2^n-1只是1在代码中应用此方法的最简单方法是以最直接的方式(递归)应用它。它适用于任何数字a,而不仅仅是2,因此我编写了将a作为参数的代码,以使其更有趣:

MyBigInt pow(MyBigInt a, int p) {
    if (!p) return MyBigInt.One;
    MyBigInt halfPower = pow(a, p/2);
    MyBigInt res = (p%2 == 0) ? MyBigInt.One : a;
    return res * halfPower * halfPower;
}

正如@Oli的回答所提到的,这不是计算2^n的问题,因为在二进制中,这只是一个1后跟0的问题

但是,由于您希望以十进制打印它们,因此这就成为了如何将非常大的数字从二进制转换为十进制的问题

我的答案是这不现实。我希望这个问题只是出于好奇

你提到试图计算2^2^31-1,然后用十进制打印出来。这个数字是6456993位

Java BigInteger无法做到这一点。它适用于小数字,用于^2算法。 正如评论中提到的,C++中没有内置的BigNem库。 即使Mathematica也无法处理它:General::ovfl:计算中发生溢出。 你最好使用图书馆。 如果您只想看到部分答案:

这是使用一个封闭源代码库完成的,在4.4 GHz的i7 2600K内核上大约需要37秒和3.2 GB的内存,包括将所有6.46亿个数字写入一个海量文本文件所需的时间。 记事本打开文件的时间比计算文件的时间长

现在要回答你的问题,在一般情况下如何计算这样的幂,@dasblinkenlight有一个答案,它是

对于大数来说,从二进制到十进制的转换是一项困难得多的任务。这里的标准算法是


我不建议您尝试实现后者,因为这远远超出了初级程序员的范围。而且在数学上也有点强:

C++中没有内置的大数类。你还想考虑流行的图书馆,还是想从问题中剔除C++?我不认为有人会指导你创建自己的Bigunm库,当优秀的图书馆已经存在GMP。知道我需要速度,我选择建立一个C++类,它对字符串进行算术运算。假设你的意思和我在谈论字符串时的想法一样,字符串是由字符构建的,对你的性能没有多大帮助,通常以可能的最大类型为基础。此外,我是否正确理解您需要2^2^31顺序的数字?在这种情况下,你真的需要尽可能快的速度,所以我建议你不要自己编写这样一个类。如果你想要二进制的答案,那么你不必做任何计算,只需写1,然后再写n-1个零,就像Oli的答案中提到的那样。但是如果你想用十进制打印答案。。。好不要指望Java的BigInteger来完成它。。。如果你说的尺寸明显大于n>2^32,也不要指望GMP能做到这一点。。。在那之前,你的内存会用完…是的,我只是没有想到位算术,那可能是最好的方法,虽然DasLinkenLight给表带来的递归方法也很有趣,我也会尝试一下。请注意使用std::string:如果使用std::vector作为表示形式,并使用额外的位来表示符号,并且确保在计算中使用unsigned long long,那么应该能够提高性能更进一步,基本上使用相同的方法。仍然没有办法存储1 Aww,我明白了,将数字存储在一个二进制数字串中,然后将其转换为十进制,这可能就行了@JimmyHuch:是的,当然,你需要想一个合适的方法来存储这个号码。但这不是你问的问题!不用担心,我想我能找到答案。1看起来它会无限递归。@kerreksb哦,你说得对!我错过了现在修复的基本案例。谢谢dasblinkenlight发布的算法是平方求幂的一种变体,这句话用词不好。你说得对,我在他的回答中忽略了半幂*半幂。更新。。。
MyBigInt pow(MyBigInt a, int p) {
    if (!p) return MyBigInt.One;
    MyBigInt halfPower = pow(a, p/2);
    MyBigInt res = (p%2 == 0) ? MyBigInt.One : a;
    return res * halfPower * halfPower;
}
2^(2^31 - 1) = 2^2147483647 = 

880806525841981676603746574895920 ... 7925005662562914027527972323328

(total: 646,456,993 digits)