2011-03-09 91 views
4

下午好,C#算術問題

從未使用過C#做嚴肅的數學工作,我剛纔注意到一些東西,給我留下了困惑......如果這是真的,

double Test = Math.Sqrt(UInt64.MaxValue) 

等於4294967296.0,就是UInt32.MaxValue + 1,那爲什麼

ulong Test2 = UInt32.MaxValue * UInt32.MaxValue; 

等於1?乍一看,在我看來,溢出發生在這裏...但爲什麼是因爲該產品應該適合UInt64

非常感謝。

回答

10

第一個發生是因爲double沒有64個尾數位,但只有53個左右。所以在轉換爲double期間,UInt64.MaxValue將四捨五入爲UInt64.MaxValue+1。而那個Sqrt顯然是2^32。 double可以完全代表(U)Int32中的任何值,但某些較大的64位整數不能表示爲double

第二個發生是因爲您在投射到UInt64之前進行了乘法運算,即發生爲UInt32,這明顯溢出。將至少一個操作數拋到UInt64,問題就會消失。

+0

是的。請給我的問題-1。非常感謝你。 – Miguel 2011-03-09 15:19:05

+0

這個問題沒有錯? – Spooks 2011-03-09 15:20:38

+6

@Miguel:我不認爲你需要-1。你犯了一個誠實的錯誤。這個問題已經得到解答,就是這樣。 – siride 2011-03-09 15:20:42

4
ulong Test2 = UInt32.MaxValue * UInt32.MaxValue 

可以翻譯成:

UInt32 __temp = UInt32.MaxValue * UInt32.MaxValue; // Overflow 
ulong Test2 = (ulong)__temp; 

上等號的左邊你沒有操作上顯然是正確的類型推論總是做你想...

不算什麼

應該已經

ulong Test2 = (long)UInt32.MaxValue * UInt32.MaxValue; 

這將被視爲:

ulong Test2 = (long)UInt32.MaxValue * (long)UInt32.MaxValue; 

而且會工作。

規則是在C#規範的章節16.4.2:

數值提升包括 自動執行某些 操作數的預定義的一元和二元 數值運算 的隱式轉換。數字提升 不是一個明顯的機制,而是 而不是將預算 分辨率應用於預定義運算符的效果。數字促銷 明確不影響 評估用戶定義的運營商, 儘管用戶定義的運營商可以將 實施爲展示類似 的效果。

作爲數值提升的一個例子,考慮 二進制* 操作者的預定 實現:

int operator *(int x, int y); 
uint operator *(uint x, uint y); 
long operator *(long x, long y); 
ulong operator *(ulong x, ulong y); 
void operator *(long x, ulong y); 
void operator *(ulong x, long y); 
float operator *(float x, float y); 
double operator *(double x, double y); 
decimal operator *(decimal x, decimal y); 

當重載決策規則 (§14.4.2)施加到該組 運營商的,其效果是從 操作數類型中選擇 隱式轉換所存在的第一個運算符 。 [例如:對於 操作b * s,其中b是字節 ,s是短的,重載分辨率 選擇運算符*(int,int)作爲 最佳運算符。因此,效果是 ,b和s被轉換爲int,並且 結果的類型是int。 同樣,對於操作i * d, (其中i是一個int並且d是雙精度), 重載決議選擇運算符 *(double,double)作爲最佳運算符。 end example]