[英]sum of positive integer returning negative number - C
C語言初學者。 我懷疑這可能是由於溢出,但無法解決這個簡單的練習:計算所有小於 10000 的自然數的平方和的程序
我最初嘗試:
#include <stdio.h>
int main() {
int a = 10000;
int square(int num) {
return num * num;
};
int total = 0;
while (a > 0) {
a--;
total += square(a);
//printf("a is %d and square is %d and total %d \n", a, square(a), total );
};
printf("total is %d ", total );
return total;
}
結果: total is -1724114088
奇怪的是:
...
a is 9936 and square is 98724096 and total 2063522144
a is 9935 and square is 98704225 and total -2132740927
...
所以我嘗試將 total 更改為long
,嘗試將聲明 square 函數更改為long square(int num )
,但沒有任何改變。
你能解釋為什么總和變成負數嗎? 是因為溢出嗎? 但是為什么不重置為 0 或正數,而不是變為負數? 我怎么知道我不知道的計算機中有多少 int 位(例如雲?例如我在這里編碼:[https://www.programiz.com/c-programming/online-compiler/]
您需要將int
所有用途更改為long
:
#include <stdio.h>
int main() {
long a = 10000;
long square(long num) {
return num * num;
};
long total = 0;
while (a > 0) {
a--;
total += square(a);
//printf("a is %ld and square is %ld and total %ld \n", a, square(a), total );
};
printf("total is %ld ", total );
return 0;
}
打印total is 333283335000
或者,您可以更改總計、 square
的返回類型,並在計算平方值時執行適當的轉換:
#include <stdio.h>
int main() {
int a = 10000;
long square(int num) {
return (long)num * (long)num;
};
long total = 0;
while (a > 0) {
a--;
total += square(a);
//printf("a is %ld and square is %ld and total %ld \n", a, square(a), total );
};
printf("total is %ld ", total );
return 0;
}
產生與上述相同的結果。
相反,您可以使用公式。
前 N 個自然數的平方和 = (N * (N + 1) * (2 * N + 1) / 6
現在,讓 N 為 10000。
忽略公式中的6,平方和有10^12那么大。 它不適合整數。 您應該使用可以容納更大值的數據類型,例如 long 或 long long int。
這是修改后的代碼。
#include <stdio.h>
int main() {
int a = 10000;
int square(int num) {
return num * num;
};
// Change int to long long int
long long int total = 0;
while (a > 0) {
a--;
total += square(a);
//printf("a is %d and square is %d and total %d \n", a, square(a), total );
};
// Change %d to %lld
printf("total is %lld ", total );
return total;
}
不要在函數中定義函數。
int main() {
int square() { // NO!
函數屬於文件范圍:
int square() { //OK
}
int main() { //OK
}
代碼編譯是因為編譯器對該語言進行了擴展。 它不是 C 編程語言的一部分。
你能解釋為什么總和變成負數嗎?
見例。 為什么 sum 的值為負? 和其他問題。 總和在您的平台上“環繞”。
是因為溢出嗎?
是的。
但是為什么不重置為 0 或正數,而不是變為負數?
因為現在的系統是二進制補碼,所以先實現一條用於加數的硬件指令,然后再實現兩條具有特殊溢出語義的獨立指令,會更簡單。 無符號和有符號二進制補碼在對它們進行運算時的行為相同,因此在添加有符號數時,與其對溢出執行特殊語義,不如將它們添加為無符號數(僅添加位),然后結果為解釋為有符號數(在 C 程序中),因為最高有效位設置為負數。
無論如何,編譯器根本不在乎,因為有符號溢出是未定義的行為,編譯器不必在意。 編譯器只生成一個用於有符號加法的硬件指令,其行為如上所述。
我怎么知道我不知道的計算機中有多少 int 位
您可以查看編譯器文檔。
但通常它更簡單,只是編譯,你用一個簡單的C程序CHAR_BIT
-位的字節數-和sizeof(int)
-字節在數int
-並檢查該程序的輸出。 例如,一個程序,例如:
#include <stdio.h>
#include <limits.h>
int main() {
printf("There are %d bits in int\n", (int)sizeof(int) * CHAR_BIT);
}
請注意,類型中的位數不僅會隨平台和操作系統而變化,還會隨編譯器、編譯器版本和編譯選項而變化。
哪個是修復它的最佳實踐?
這取決於您想要什么樣的行為。
要計算更大的值使用更大的數據類型- long
或long long
。 當語言功能不夠時,請移動您的程序使用一些大數字庫。
如果您想在出現問題時終止程序 - 您可以檢查溢出並在發生時調用abort()
或類似方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.