使用指数溢出计算最大长值
Calculating max long value using exponent overflows
我试图通过计算基数 2
的指数来计算类型 long
的最大值。
不幸的是,计算在第 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
执行此操作时,它工作正常。
这里的代码有一个差一错误。
考虑以下问题:exponential(10, 2)
的结果是什么?经验调试(使用printf
语句)显示是1000。所以exponential
计算数学表达式be+1.
long
类型通常有64位。这似乎是你的情况(看到溢出发生在第 64 步左右)。看到它是一个有符号类型,它的范围(通常)是从 -263 到 263-1。即该数据类型所能表示的2的最大次方为262;如果代码尝试计算 263,则会发生溢出 (you probably want to avoid it).
因此,由于差一错误,代码将导致 exponent
大于或等于 62 的溢出。
要修复差一错误,请从 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
数据类型不能表示数字263。幸运的是,您可以使用 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));
我试图通过计算基数 2
的指数来计算类型 long
的最大值。
不幸的是,计算在第 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
执行此操作时,它工作正常。
这里的代码有一个差一错误。
考虑以下问题:exponential(10, 2)
的结果是什么?经验调试(使用printf
语句)显示是1000。所以exponential
计算数学表达式be+1.
long
类型通常有64位。这似乎是你的情况(看到溢出发生在第 64 步左右)。看到它是一个有符号类型,它的范围(通常)是从 -263 到 263-1。即该数据类型所能表示的2的最大次方为262;如果代码尝试计算 263,则会发生溢出 (you probably want to avoid it).
因此,由于差一错误,代码将导致 exponent
大于或等于 62 的溢出。
要修复差一错误,请从 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
数据类型不能表示数字263。幸运的是,您可以使用 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));