2014-07-05 81 views
-1

我想編寫一個程序來計算由n行組成的區域數。 第一個例子是我的代碼,第二個例子是我朋友的代碼。我認爲他們正在嘗試做同樣的事情,但對於n = 65535的情況,我的代碼給了我錯誤的答案。我的代碼中的問題在哪裏?無法理解這兩個代碼示例之間的區別

我的代碼:

#include<iostream> 
using namespace std; 

int main() 
{ 
    int n; 
    cin >> n; 

    unsigned long long ans; 
    ans = (n*(n + 1)/2) + 1; 
    cout << ans << endl; 

    return 0; 
} 

我朋友的代碼:

#include <iostream> 

using namespace std; 

int main(void){ 
double n,sum; 
cin>>n; 
sum=n*(n+1)/2+1; 
cout<<(long)sum<<endl; 
return 0; 
} 
+1

也許你的朋友知道。 – demoncodemonkey

+1

你在32位機器上嗎?然後它是int溢出。你的朋友的代碼使用雙倍,所以有更多的範圍。 – Dithermaster

回答

4

在您的代碼:

int n; 
ans = (n*(n + 1)/2) + 1; 

在計算所有的值都是整數:n被聲明爲INT,和純整數常量也是整數。因此這個計算的結果也將是一個整數。後來將此結果分配給long long變量的事實不會改變這一點。

現在乘法65535 * 65536的結果不符合32位signed int,因此您會得到一個無意義的答案。通過使n長64位來修復您的程序。

4

正如@Dithermaster所說,這裏的問題可能是整數溢出之一。

就像現在這樣,你的代碼實際上並沒有什麼意義。特別是,由於您定義nint,和在表達式中的所有整數常量:(n*(n + 1)/2) + 1也足夠小以適合在int,計算將在int s,然後(後進行計算已完成),結果將轉換爲long long並分配給ans(因爲您已將ans定義爲long long)。

你幾乎可以肯定想要是爲了避免溢出而對long long進行整個計算。最明顯的做法是將n定義爲long long而不是int

你的朋友已經通過將n定義爲double來避免這種情況。這工作到一定程度 - double的典型實現有一個53位有效數,所以它可以用作(實質上)一個53位整數類型。這顯然比一個int強制執行的16位多一點,但同樣明顯低於long long強制執行的64位。

支持n也沒有意義,因此您可以考慮將nans改爲unsigned long long