在C中解决2到20万的功率

时间:2012-11-26 09:10:22

标签: c math

我如何解决:C {中的2 ^ 200'000 我尝试了几种解决方案:

unsigned long long int variable = 1;
int i = 0;
 for(i = 0; i < 200000; i++) {
        variable *= 2;
 }
 printf("%llu", variable);

我得到了结果:0

我也累了:

variable = 1 << 200000;

我得到了相同的结果

也是:

pow(2, 200000);

我得到了结果:inf

我知道结果将是一个非常大的数字!

6 个答案:

答案 0 :(得分:6)

您需要使用bignums。提供它们的好C库是GMPlib(或 Gmp )。

另见this&amp; this回答。

如果是家庭作业,你必须避免使用外部库,那么通过在例如大数字中表示大数字来实现你自己的天真和低效的bignum操作。基数1000000000作为bigdigits的向量(在基数1000000000中,即unsigned int - s小于1000000000)。但请注意,有效的bignum操作算法是一个非常困难的主题(你可以在其上做博士)。

使用的Common Lisp(实际上在Linux SBCL),(expt 2 200000)给出了大量的位数,与920038457001984739009853229094231266558782271736355646970683344733851701497060850614781367869193252027245901165192794172829673551622776804677516046034691191314830879238153864550662072000140791040750506601286234544337124194554552216233147391907942666374197047501518768776635660639895886684528408599509875931170744171632720906652165051356810584676925732763418087079259790326514074925059567293113070694950457694751972448438483214134115453746217764408771372456029214052022079066814407632012911631016804966554137474010944697979109376结束

答案 1 :(得分:3)

你会如何尝试用铅笔和纸张在教室里解决这个问题20或100次?同样的方法在这里也是完美的。我只是建议反转数组,这样就可以从左到右相乘,只需按照正确的顺序打印最终数字。

答案 2 :(得分:3)

如果你不能使用外部bignum库,那么你必须实现自己的。

首先定义你的大号在内存中的样子。例如,对于有理数(最令人敬畏的数字),数字可能表示为“a / b *(2 ** e)”;你可能有一个可变大小的无符号字节数组来表示一个分母,一个用于表示除数的无符号字节的可变长度数组,一个用于表示指数的无符号字节的可变长度数组,以及一些标志(例如分母符号和指数符号) )。

下一步是编写代码来对你的大数字进行原始操作。例如,用于将可变长度数组添加到一起的代码,用于向左/向右移动可变长度数组的代码,用于将2个可变长度数组相乘的代码等等。

下一步是使用原始操作实现正常操作。例如(对于有理数),“bigNumber&lt;&lt; 44”实际上是“a / b *(2 ** e)&lt;&lt; 44”,并且你只需要将44添加到“e”。 / p>

下一步是使用您实施的常规操作将您的号码转换为您的格式。例如,您可以创建一个大数字,其值为1(分母= 1,除数= 1,指数= 0),然后将其向左移动200000(分母= 1,除数= 1,指数= 0 + 200000)。

当然,您需要一些方法将您的大号转换为字符串,以便显示它。这需要实际划分(而不是“反向乘法”),这很棘手。

请注意,出于您的目的,您实际上只需要一个“0位”有效数字和一个18位指数来存储数字(采用专门为该数字设计的格式)。如果您不需要以十进制显示结果数字,那么它就变得非常容易了。

例如,要以十六进制显示,您可以执行以下操作:

char hexDigitTable[16] = "0123456789ABCDEF";

// My big number with a 0-bit significand and 18-bit exponent!
uint32_t exponent = 20000;     

printBigNumber(uint32_t exponent) {
    int digit;

    if(exponent > 4) {
        // Note: "number / 16" is the same as "number >> 4" which is
        //       the same as "exponent - 4".
        printBigNumber(exponent - 4);
    }
    digit = 1 << (exponent & 3);
    printf("%c", hexDigitTable[digit]);
}

如果你懒惰,看看有多容易? : - )

答案 3 :(得分:2)

您无需“计算”任何内容。基数2是特殊的 - 它是二进制基数 - 并且以2 ^ x的形式的2的幂可以被生成为1&lt;&lt;&lt; x(左移)。您需要设置一个可以保存至少200,000位的位域,例如unsigned char [25000]并将最高位设置为1.然后,您只需将此位域解释为整数。

以十六进制写出这个数字是微不足道的 - 只需用十六进制写出每个字节。要以十进制打印出来,您可能需要一个bignum库:(

答案 4 :(得分:0)

为此,您需要某种形式的bignum library,C中没有本机数据类型将能够准确保存此数字。请注意,表示此数字需要相当多的内存。

答案 5 :(得分:0)

2 ^ 200000远远超出任何内置数据类型。

您需要在数组中表示权力以手动模拟乘法。

例如,您可以使用数组{0,1,2,3,4,5,6,7,8,9}来存储9,876,543,210。

其次,您应该使用分而治之算法来降低计算复杂度。

为了计算

a ^ b

你需要计算

t = a ^ (b/2)

第一。然后用t来计算

a ^ b = t * t * a ^ ( b % 2 )