我试图通过计算基数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);
运行该函数后, lResult
为0
。
奇怪的是,当我为char
,short
和int
执行此操作时,它可以正常工作。
答案 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));