2014-10-30 24 views
0

我偶然發現了Convert這個奇怪的行爲,我想分享一下。Convert.ToInt小數和雙數的奇怪舍入

Convert.ToInt(16,32,64)的方法在一種奇怪的方式上doubledecimal型圓當用於

從MSDN:

轉換後的值被四捨五入爲簽署的最近的16位整數。如果 的值是兩個整數之間的中間值,則返回的偶數爲 ;也就是4.5被轉換爲4,並且5.5被轉換爲6.

這是一個非常奇怪的行爲,它可能導致很難找到錯誤。

我看着與反射器所分析的代碼,但它是一個extern方法:

//Convert.ToInt32 
[SecuritySafeCritical, __DynamicallyInvokable] 
public static int ToInt32(decimal value) 
{ 
    return decimal.FCallToInt32(value); 
} 

//decimal 
[MethodImpl(MethodImplOptions.InternalCall), SecurityCritical] 
internal static extern int FCallToInt32(decimal d); 

我知道Convert類是指將一基本數據類型到另一種數據類型的,它不應該被用於四捨五入的價值,但你會同意,我們將不得不期待一個標準的四捨五入。

我的問題是,爲什麼這種行爲,爲什麼它是大紅色的字體在MSDN上

+0

它銀行家四捨五入,你需要在任何統計應用程序中使用它,否則數量與大量套向上歪斜。 – flindeberg 2014-10-30 14:05:36

+0

請參閱[文檔](http://msdn.microsoft.com/zh-cn/library/system.math.round(v = vs.110).aspx),標題爲「舍入到最近位置」或銀行家舍入「。也就是說,框架中的「爲什麼」這樣的問題的行爲方式通常被認爲不具有建設性。 – 2014-10-30 14:06:13

+0

ops我發誓我在提問之前在stackoverflow中搜索,但沒有找到任何東西。對不起,重複! – giammin 2014-10-30 14:09:08

回答

2

不加蓋它被稱爲銀行家舍,它的特別是在金融應用中使用。由於decimal專爲金融應用而設計,因此它很明顯,它爲什麼是decimal的默認舍入方法,不是嗎? :)

它背後的想法是,如果你總是舍入一種方式,.5數字會打破數字的分佈,或換句話說,你的舍入誤差會積累顯着。通過基於均勻度進行舍入或舍入,您通常最終會在這些情況下佔用50%的時間,其餘時間則會減少 - 因此錯誤將保持非常小。

這一點是使用長計算機之前:)

+0

好的,但它爲什麼複製雙打... – giammin 2014-10-30 14:04:52

+0

如果它沒有複製雙打,這將是不一致的。 – DavidG 2014-10-30 14:06:18

+0

@giammin它並不重要。將'x.5'作爲'double'幾乎是不可能的,因爲二進制浮點不是十進制精確的,只是二進制精確的。所以你可以表示的唯一真正的'.5'數字是'0.5'。實際上,'double'會自動「做這種事情」,因爲你總是會得到像'2.50000001'這樣的數字,它首先不是*中點。 – Luaan 2014-10-30 14:06:43