我编写了这段代码以找到第 x 个最大的质数:
for (int i = 3 /* 2 has already been added to the list */; i < maxNumber; i += 2) {
for (int tested = 0; ; tested++) {
if (primes[tested] == 0) {
break;
}
if (i % (int) primes[tested] == 0) {
goto loop;
}
}
count++;
if (count == primesSize) {
primesSize += 2000;
primes = (double*) realloc(primes, sizeof(double) * primesSize);
}
primes[count - 1] = i;
printf("Prime number #%d: %d\n", count, i);
printf("Prime size: %d\n", primesSize);
loop: /* statement that does nothing */ if (1) {}
}
但是,当使用大数(> 8,000)时,它会返回“浮点异常”。
什么时候发生在这里:
maxNumber
设置为所选数字的平方根。1000 * sizeof(double)
的双指针。它存储在primes
变量中。primes
指针将重新分配以存储另外2,000个数字。当我使用gdb
找出错误的原因时,我发现这是造成问题的原因:
for (int tested = 0; ; tested++) {
if (primes[tested] == 0) {
break;
}
if (i % (int) primes[tested] == 0 /* breaks here */) {
goto loop;
}
}
更新:我认为第一个if
语句会解决该问题,因为printf("%f", primes[tested])
会显示0。但是,不会,并且不会执行“ break”
代码中断时,tested
为1001。我将primes[tested]
转换为整数,因为我使用的modulo arithmetic operation需要整数才能工作。但是,当我从代码中打印primes[tested]
时,它显示为 0 。如果我从gdb打印该值,则会得到 6.1501785659964211e-319 。
我想念什么?我应该修改对realloc
的呼叫以避免这种异常吗?
答案 0 :(得分:3)
我认为第一个
if
语句会解决该问题,因为printf("%f", primes[tested])
打印0。但是,不会,并且 “ break”未执行。
您测试是否为primes[tested] == 0
,但是您的代码仅在((int)primes[tested]) == 0
时有效。这些根本不是一回事。此外,以格式primes[tested]
打印%f
的值并不能可靠地告诉您其他信息,因为它只给小数点后6位数字。请尝试使用"%e"
格式,并测试您实际需要的条件,而不是相关的较弱的条件。
但更好的是,不要在此处使用浮点类型。 FP与离散数学问题无关,例如您似乎正在尝试解决。如果primes[tested]
实际上拥有素数或可能的素数,则unsigned long long int
的大小可能与double
相同,并且几乎可以肯定地表示更大范围的素数。或者,如果它仅包含标志(例如质数筛),那么任何比char
宽的内容都是浪费的。
答案 1 :(得分:2)
非常接近的浮点数仍然不是零。因此,您的等于0检查失败。
请注意,如果您对使用的机器类型不太满意,甚至可以编译
double f = 1.1;
double x = f;
double y = x;
if( y == f )
puts("This is not always true!");
计算机上的浮点运算很棘手,并且无法按定义编写x等于y等于f的数学公式工作。不,计算机浮点运算适用于位模式,它们必须完全相同。
无论如何,回答您的问题。使用与if语句中的if语句完全相同的int类型,它应该可以工作。
从realloc
返回的新内存也不会自动设置为零。
还有第三个:如果必须使用realloc
强制转换(double*)
的返回值,则说明您使用的是C ++编译器,应该使用std::vector<double>
。真的好多了。否则,如果您正在编写C代码,则编写C代码。
答案 2 :(得分:0)
我认为第一个if语句将解决该问题,因为 printf(“%f”,primes [test])打印0。
如果此打印语句根据您的发言给出正确的输出,那么显然select typeof(field1), typeof(field2) from cte2
是有意义的。
您正在考虑if语句应该处理异常,但是实际上并没有像您所想的那样执行。首先,它执行with
cte1 as (...),
cte2 as (... from cte1)
describe select * from cte2
部分,然后将结果与Floating point exception
进行比较。因此,显然,即使在if可以运行之前,也会发生异常。希望你能理解。
仅供参考,如果i % (int) primes[tested]
,则0
会导致浮点异常。
如果您对if语句的执行步骤有更多疑问,请自己运行以下代码:
b = 0
然后尝试了解哪个a % b
首先执行。