[英]Why am I getting a return value of -1 (0xFFFFFFFF)?
我最近開始學習我的第一門編碼語言c。 我正在嘗試解決Euler項目中的問題3,我這樣做是為了解決這個問題。 該代碼旨在標識最大的素數600851475143,但是相反,我得到了一個我不理解的奇怪的返回值。 有人知道為什么嗎?
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i = 1, a = 0, prime = 0;
for(i = 1; i < 600851475143; i += 2) {
for(a = 0; a <= i / 2; a++) {
if(i % a == 0) {
break;
}
if(a = i / 2) {
if(600851475143 % i == 0) {
prime = i;
}
}
}
}
printf("%d\n", prime );
return 0;
}
除以0(或嘗試除以%0
)。 這是未定義的行為 (UB),可以解釋-1的返回。 有了UB, 一切都會發生。 在修復此問題之前,其余代碼並不重要。
for(a = 0; a <= i / 2; a++) {
// v---- a is zero!
if(i % a == 0) {
代碼可能應該從2開始。
// for(a = 0; a <= i / 2; a++) {
for(a = 2; a <= i / 2; a++) {
而不是結束於i / 2
,結束於√600851475143,它要早得多 。
v-------------------v Same a <= sqrt(600851475143) without FP or overflow
for(a = 2; a <= 600851475143 / a; a++) {
也存在其他問題。 if(a = i / 2)
參見@Tom Karzes
int
的范圍很可能在600851475143之內,因此i < 600851475143
始終為真。 常見的編譯器警告將發出此警告。 確保完全啟用警告以節省時間。 @iBug
warning: comparison is always true due to limited range of data type [-Wtype-limits]
偽代碼解決方案
int main(void) {
wide_enough_type n = 600851475143;
wide_enough_type factor = 1;
try each i starting at 2 and until i*i <= n
repeat as long as n divides into i with no remainder
make n smaller by diving it by i
save i as factor
save the larger of (n, factor) as factor
printf("Greatest factor: %some_type_specifier\n", factor);
}
您的問題稱為溢出 。 由於可用內存的限制,所有數據類型的范圍都有限。 在一般的現代計算機上,一個int
通常最多可以達到2,147,483,647(警告:我通常這樣說)-實際上情況要復雜一些。 無論如何,您的上限都超過了這個上限。
當int
(或帶符號的整數數據類型)溢出時,由於與表示相關的一些問題,它變為負數。 有關原因的更多詳細信息,請查看二進制補碼表示形式 。
要解決此問題,請使用范圍更廣的數據類型。 long long
達到9,223,372,036,854,775,807,這似乎很適合您的需求。
請注意,整數文字也需要標記為long long
,否則它們也會溢出:
for(i = 1; i < 600851475143LL; i += 2)
如果您需要的整數值大於long long
支持的范圍(雖然這里似乎不是這種情況),那么您就不走運了:您需要找到一些巧妙的方法來處理它。
其他需要查找的是,當我運行代碼時,我將其除以0。我不知道這是否與溢出有關。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.