您当前的位置: 首页 > 学无止境 > 心得笔记 网站首页心得笔记
第31讲-错误处理和调试2-ULONG_MAX
发布时间:2021-05-19 21:51:38编辑:雪饮阅读()
一个有隐患的阶乘
在之前我们曾经实现过阶乘,那么一般一个阶乘的程序如:
#include <iostream>
//unsigned:無符號,不包含負數
unsigned long returnFactorial(unsigned short num){
unsigned long sum=1;
for(int i=1;i<=num;i++){
sum*=i;
}
return sum;
}
int main(){
unsigned short num;
std::cout<<"請輸入一個整數:";
std::cin>>num;
std::cout<<num<<"的階乘結果是:"<<returnFactorial(num)<<"\n";
return 0;
}
当我们编译并输入一个比较小的数字时候,阶乘是正确的:
請輸入一個整數:7
7的階乘結果是:5040
Process returned 0 (0x0) execution time : 13.530 s
Press any key to continue.
那么当我们输入一个较大的数字的时候:
虽然程序正常运行,也没有报错信息。
但是这里阶乘的结果很明显有问题了。
这就是这里所说的阶乘的隐患。
用ULONG_MAX来修缮阶乘隐患
ULONG_MAX常量是在climits标头中定义的宏常量,用于获取无符号long int对象的最大值,它返回无符号long int对象可以存储的最大值,即18446744073709551615 (在32位编译器上) )。
那么可以利用此特性,进行阶乘能力的预判,进而给用户一个友好的提示,而并非上面一样直接数据过大了就返回一个对于用户来说是一个错误的值,这样容易误导用户。
那么具体的实例如:
#include <iostream>
#include <climits>
class Factorial{
public:
Factorial(unsigned short num){
this->num=num;
};
//获取阶乘
unsigned long getFactorial(){
unsigned long sum=1;
for(int i=1;i<=num;i++){
sum*=i;
}
return sum;
};
/*
判断输入数字是否在阶乘范围内
假设输入数为5,max初始值为10,那么10/5/4/3/2/1,实际上这里只到10/5的时候就已经不足以除以4了,小于1了(2/4)
基于此阶乘反向求极限的原理可以预判输入数是否超过当前程序(环境)所能计算阶乘的能力
同时由此原理,如果输入数过大,则也可以计算当前程序环境的阶乘能力最大值(在for循环中结合max<1计算循环次数)
ULONG_MAX常量是在climits标头中定义的宏常量,用于获取无符号long int对象的最大值,它返回无符号long int对象可以存储的最大值,即18446744073709551615 (在32位编译器上) )。
*/
bool inRange(){
unsigned long max=ULONG_MAX;
for(int i=num;i>=1;--i){
//相当于max=max/i
max/=i;
}
if(max<1){
return false;
}
else{
return true;
}
}
private:
unsigned short num;
};
int main(){
unsigned short num=0;
std::cout<<"請輸入一個整數:";
std::cin>>num;
Factorial fac(num);
if(fac.inRange()){
std::cout<<num<<"的階乘值是"<<fac.getFactorial()<<"\n\n";
}
else{
std::cout<<"您所輸入的值太大!\n\n";
}
return 0;
}
编译运行结果如:
請輸入一個整數:13
您所輸入的值太大!
Process returned 0 (0x0) execution time : 1.495 s
Press any key to continue.
再来用一个比较小的数字来测试:
請輸入一個整數:7
7的階乘值是5040
Process returned 0 (0x0) execution time : 2.008 s
Press any key to continue.
可见这里已经修复ok了
关键字词:ULONG_MAX,阶乘,climits
上一篇:第30讲-错误处理和调试