防止用户输入会导致整数溢出的值
Prevent a user from entering a value which would cause integer to overflow
我是 C++ 编程的新手,编写了一个简单的程序来计算用户提供的整数的阶乘。我正在尝试考虑会导致错误或没有意义的输入(例如,我已经考虑了负 number/-1 的输入)。如果用户输入一个阶乘大于最大整数大小的数字,我想打印出一个错误。
我开始于:
if(factorial(n) > INT_MAX)
std::cout << "nope";
continue
我用 n = ~25 或 26 对此进行了测试,但它并不能防止结果溢出并打印出一个大的负数。
其次,我尝试使用 'limits.h'
header 中的函数将其分配给变量,然后将 factorial(n)
的结果与此进行比较。仍然不走运(您可以在下面的代码示例中看到此解决方案)。
我当然可以将结果分配给 long
并针对它进行测试,但在您开始环绕该值之前,您也不必走得太远。如果发生这种情况,我更愿意找到一种方法来简单地防止打印该值。
#include <iostream>
#include <cstdlib>
#include <limits>
int factorial(int n)
{
auto total = 1;
for(auto i = 1; i <= n; i++)
{
total = total * i; //Product of all numbers up to n
}
return total;
}
int main()
{
auto input_toggle = true;
auto n = 0;
auto int_max_size = std::numeric_limits<int>::max();
while(input_toggle = true)
{
/* get user input, check it is an integer */
if (factorial(n) > int_max_size)
{
std::cout << "Error - Sorry, factorial of " << n << " is larger than \nthe maximum integer size supported by this system. " << std::endl;
continue;
}
/* else std::cout << factorial(n) << std::endl; */`
与我的其他条件一样,我希望它只是打印出那条小错误消息,然后继续要求用户输入以进行计算。该代码确实有效,如果我请求值 >25 左右的阶乘,它只会继续打印已环绕的值。我觉得这种error-checking会很有用
谢谢!
您正在尝试倒退。
首先,实际上没有整数可以大于INT_MAX
,根据定义——这是一个整数可以的最大值!所以你的条件 factorial(n) > int_max_size
永远是假的。
此外,您的方法存在逻辑缺陷。您首先计算该值,然后检查它是否小于允许的最大值。到那个时候就太晚了!您已经计算了该值并经历了您可能遇到的任何溢出。您可能正在执行的任何检查都应该在您仍在进行计算时执行。
本质上,您需要检查 X
乘以 Z
是否在允许的范围内而不实际执行乘法(不幸的是,C++ 非常严格地保留有符号整数溢出未定义的行为,所以你不能试试看。)。
那么如何检查 X * Y
是否小于 Z
?一种方法是在进行计算之前将 Z
除以 Y
。如果你最终得到的数字小于 X
,你就会知道 X
乘以 Y
会导致溢出。
我相信,您知道有足够的信息来自己编写解决方案。
我是 C++ 编程的新手,编写了一个简单的程序来计算用户提供的整数的阶乘。我正在尝试考虑会导致错误或没有意义的输入(例如,我已经考虑了负 number/-1 的输入)。如果用户输入一个阶乘大于最大整数大小的数字,我想打印出一个错误。
我开始于:
if(factorial(n) > INT_MAX)
std::cout << "nope";
continue
我用 n = ~25 或 26 对此进行了测试,但它并不能防止结果溢出并打印出一个大的负数。
其次,我尝试使用 'limits.h'
header 中的函数将其分配给变量,然后将 factorial(n)
的结果与此进行比较。仍然不走运(您可以在下面的代码示例中看到此解决方案)。
我当然可以将结果分配给 long
并针对它进行测试,但在您开始环绕该值之前,您也不必走得太远。如果发生这种情况,我更愿意找到一种方法来简单地防止打印该值。
#include <iostream>
#include <cstdlib>
#include <limits>
int factorial(int n)
{
auto total = 1;
for(auto i = 1; i <= n; i++)
{
total = total * i; //Product of all numbers up to n
}
return total;
}
int main()
{
auto input_toggle = true;
auto n = 0;
auto int_max_size = std::numeric_limits<int>::max();
while(input_toggle = true)
{
/* get user input, check it is an integer */
if (factorial(n) > int_max_size)
{
std::cout << "Error - Sorry, factorial of " << n << " is larger than \nthe maximum integer size supported by this system. " << std::endl;
continue;
}
/* else std::cout << factorial(n) << std::endl; */`
与我的其他条件一样,我希望它只是打印出那条小错误消息,然后继续要求用户输入以进行计算。该代码确实有效,如果我请求值 >25 左右的阶乘,它只会继续打印已环绕的值。我觉得这种error-checking会很有用
谢谢!
您正在尝试倒退。
首先,实际上没有整数可以大于INT_MAX
,根据定义——这是一个整数可以的最大值!所以你的条件 factorial(n) > int_max_size
永远是假的。
此外,您的方法存在逻辑缺陷。您首先计算该值,然后检查它是否小于允许的最大值。到那个时候就太晚了!您已经计算了该值并经历了您可能遇到的任何溢出。您可能正在执行的任何检查都应该在您仍在进行计算时执行。
本质上,您需要检查 X
乘以 Z
是否在允许的范围内而不实际执行乘法(不幸的是,C++ 非常严格地保留有符号整数溢出未定义的行为,所以你不能试试看。)。
那么如何检查 X * Y
是否小于 Z
?一种方法是在进行计算之前将 Z
除以 Y
。如果你最终得到的数字小于 X
,你就会知道 X
乘以 Y
会导致溢出。
我相信,您知道有足够的信息来自己编写解决方案。