C++ 为什么一个大的数字输入会为这个代码生成一个运行时错误来计算primeCounting?

C++ 为什么一个大的数字输入会为这个代码生成一个运行时错误来计算primeCounting?,c++,c++11,count,runtime-error,primes,C++,C++11,Count,Runtime Error,Primes,任务是计算输入参数N以下的素数。 我正在用从小到大的不同输入数测试这段代码。非常奇怪,我只在输入值大于等于46342时遇到运行时错误。如果输入值小于46342,则代码运行良好,没有任何运行时错误 int countPrimes(int n) { if (n <= 2) return 0; vector<bool> array(n,true); int cnt = 0; for (int i = 2 ; i < n ; i++) {

任务是计算输入参数N以下的素数。 我正在用从小到大的不同输入数测试这段代码。非常奇怪,我只在输入值大于等于46342时遇到运行时错误。如果输入值小于46342,则代码运行良好,没有任何运行时错误

int countPrimes(int n) {
    if (n <= 2) return 0;
    vector<bool> array(n,true);
    int cnt = 0;
    for (int i = 2 ; i < n ; i++)
    {
        for (int j = i ; i * j < n ; j++)
        {

            int product = i * j;
            if (array[product])
            {
                array[product] = false;
                cnt++;
            }
        }
    }
    return n - 2 - cnt;
}
int countPrimes(int n){
如果(n1),则:

将溢出,使
产品
等于负数

然后,您将尝试使用负索引访问
array
(实际上是一个向量,因此将其命名为
array
不是一个好的选择),这将导致程序崩溃


您需要使用能够支持更大数值的类型。现在您使用了
int
()。对于
n
i
j
、以及
product

int product = i * j;
将溢出,使
产品
等于负数

然后,您将尝试使用负索引访问
array
(实际上是一个向量,因此将其命名为
array
不是一个好的选择),这将导致程序崩溃



您需要使用能够支持更大数值的类型。现在您使用了
int
()。对于
n
i
j
、和
product
使用
int
的最大值是2的31次方,等于2147483648。

这个值的平方根是46340.95,因此您正在使用的值(通过执行
i*j
)超过该限制,导致运行时异常。

int
的最大值是2的31次方,等于2147483648。

这个值的平方根是46340.95,因此您正在使用的值(通过执行
i*j
)超过该限制,导致运行时异常。

如其他答案中所述,OP遇到的是两个问题的组合,整数溢出和向量的越界访问,这两个问题都是未定义行为的原因

线路

int product = i * j;
声明一个
int
变量,该变量初始化为
i
j
的乘积,其类型为
int
,引用

如果不存在长度修饰符,则保证其宽度至少为16位。然而,在32/64位系统上,几乎完全保证其宽度至少为32位

显然,在OP的系统中,
int
具有32位宽度,因此大于46341的
i
值使操作46342*46342=2147580964溢出可表示数字的范围(int_MAX可能是2147483647)

在溢出的情况下,行为是未定义的,但在大多数体系结构中,整数以2的补码表示,可以获得负数,这导致未定义行为的另一个原因,可能是问题中提到的“运行时错误”:

if (array[product])   // <- 'product' can be negative
                      //  'array.at(product)' would have caught this error
{
    array[product] = false;
//…

if(array[product])/如其他答案所述,OP遇到的是两个问题的组合,整数溢出和向量越界访问,这两个问题都是导致未定义行为的原因

线路

int product = i * j;
声明一个
int
变量,该变量初始化为
i
j
的乘积,其类型为
int
,引用

如果不存在长度修饰符,则保证其宽度至少为16位。然而,在32/64位系统上,几乎完全保证其宽度至少为32位

显然,在OP的系统中,
int
具有32位宽度,因此大于46341的
i
值使操作46342*46342=2147580964溢出可表示数字的范围(int_MAX可能是2147483647)

在溢出的情况下,行为是未定义的,但在大多数体系结构中,整数以2的补码表示,可以获得负数,这导致未定义行为的另一个原因,可能是问题中提到的“运行时错误”:

if (array[product])   // <- 'product' can be negative
                      //  'array.at(product)' would have caught this error
{
    array[product] = false;
//…

if(array[product])//您可以简单地打印出
product
的值来查看错误。您可以简单地打印出
product
的值来查看错误。感谢您的帮助。我在循环条件中考虑了(int j=I;I*ji*j
overflows@newbie,所以您试图计算以保护它的表达式也有错误。您必须使用更大的数据类型,例如
unsigned int
,或
long int
。我明白了。非常感谢,这确实解决了我的问题m、 欢迎您@newbie。欢迎来到Stack Overflow,您发布了一个很好的第一个问题,这就是我投票给您的原因。别忘了接受这里发布的答案。感谢您的帮助。我在循环条件中考虑了(int j=I;I*ji*j
overflows@newbie,所以您试图计算以保护它的表达式也有错误。您必须使用更大的数据类型,例如
unsigned int
,或
long int
。我明白了。非常感谢,这确实解决了我的问题m、 欢迎@newbie。欢迎来到Stack Overflow,你发布了一个很好的第一个问题,这就是为什么我投票给你。别忘了接受这里发布的答案。非常感谢各位,上面的答案确实解决了我的问题。我非常感谢。非常感谢各位,上面的答案确实解决了我的问题。我非常感谢1.非常感谢鲍勃的详细解释非常感谢鲍勃的详细解释