C中的幂函数为大数字提供相同的输出

时间:2017-02-02 15:47:40

标签: c exponentiation

problem statement要求我查找^ b的最后一位数字。 约束是0 <= a <= 20且0 <= b <= 2,147,483,000。

我的代码适用于12 ^ 8或6 ^ 9或类似的数字。 但是当我移动到大数字区域时,例如14 ^ 1234或17 ^ 148713,我总是得到-8的输出。

#include <stdio.h>
#include <math.h> 
int main() {
    int t;
    scanf("%d", &t);
    while(t--)
    {
        int a;
        long long int b;
        double x, y, res;
        scanf("%d %lld", &a, &b);
        x=(double)a;
        y=(double)b;
        res = pow(x, y);
        int rem;
        rem = (int)res%10;
        printf("%d\n", rem);
    }
    return 0; }

这种奇怪的输出可能是什么原因?

除了将大数字存储在数组中之外没有办法解决(我想像How to calculate 2 to the power 10000000这样的东西)?

2 个答案:

答案 0 :(得分:1)

int可以保存最多包含2 ^ 31 - 1的值,因此您基本上有溢出(实际上它导致未定义行为与溢出无符号类型相反)。

正如@PaulR在对您的问题的评论中已经指出的那样,一般的想法是滥用模幂运算的某些属性。简而言之:您需要保持数字“足够小”以防止防止溢出并能够获得所需的结果。

我们可以使用以下属性:(a * b) % m == (a % m) * (b % m)。在代码中它看起来像这样:

const unsigned int m = 10;  // our modulus
while(t--)
{
    ...                     // read 'a' and 'b'

    unsigned int res = 1;   // last digit of a^b (e.g. res == (a^b % m))
    for (unsigned int i = 0; i < b; ++i)
    {
        res *= a;           // rising to power i
        res %= m;           // keep res small !
    }

    ...                     // you get desired result
}

注意:ab声明为unsigned int - 这对您的限制就足够了,可以防止签名和无符号之间的无关和无意转换。

答案 1 :(得分:0)

请参阅Integer Overflow了解为什么它是负数,至于为什么值总是-8,那么比我聪明的人会回答那个。