使用指数溢出计算最大长值

时间:2017-09-25 20:29:32

标签: c exponential

我试图通过计算基数long的指数与位数的幂来计算出类型2的最大值。

不幸的是,计算在第61步溢出,我不明白为什么。

long exponential(int base, int exponent)
{
    long result = (long)base;
    for (int i = 0; i < exponent; i++) {
        result *= base;
    }
    return result;
}

unsigned int sLong = sizeof(long);

long lResult = exponential(2, (sLong * 8) - 1);
运行该函数后,

lResult0

奇怪的是,当我为charshortint执行此操作时,它可以正常工作。

1 个答案:

答案 0 :(得分:2)

此处的代码有一个错误。

请考虑以下问题:exponential(10, 2)的结果是什么?经验调试(使用printf语句)表明它是1000.所以exponential计算数学表达式b e + 1

long类型通常有64位。这似乎是你的情况(看到溢出发生在第64步)。看到它是带符号的类型,其范围(通常)从-2 63 到2 63 -1。也就是说,数据类型可以表示的2的最大功率是2 62 ;如果代码试图计算2 63 ,则会发生溢出(you probably want to avoid it)。

因此,由于出现了一个错误,代码将导致exponent溢出大于或等于62.

要修复off-by-one错误,请从1:

开始相乘
long power_of(int base, int exponent)
{
    long result = (long)1; // 0th power of base is 1
    for (int i=0; i<exponent;i++) {
        result*=base;
    }
    return result;
}

但是,这不会消除溢出,因为long数据类型不能代表数字2 63 。幸运的是,您可以使用unsigned long long,这对于您正在进行的计算类型保证足够大:

unsigned long long power_of(int base, int exponent)
{
    unsigned long long result = 1ULL; // 0th power of base is 1
    for (int i=0; i<exponent;i++) {
        result*=base;
    }
    return result;
}

使用llu格式打印:

printf("%llu", power_of(2, 63));