2012-12-10 29 views
1
var numberFormat = new NumberFormatInfo(); 
numberFormat.NumberDecimalSeparator = "."; 
numberFormat.NumberDecimalDigits = 2; 

decimal a = 10.00M; 
decimal b = 10M; 

Console.WriteLine(a.ToString(numberFormat)); 
Console.WriteLine(b.ToString(numberFormat)); 
Console.WriteLine(a == b ? "True": "False"); 

在控制檯: 10.00 真奇數小數類型的行爲

它爲什麼不一樣?更重要的是,不管變量如何初始化,我如何調用ToString()來確保輸出相同。

+0

您期待什麼輸出? 10,10,是真的嗎? –

+0

嗯,我有點希望10.00 10.00是真的,但至少應該清楚numberFormat是錯誤的,如果它是10 10真實的。這只是讓我感到困惑(因爲我的實際代碼並不那麼簡單,需要一些時間才能弄清楚爲什麼數字格式可以保留一位小數,但錯誤的是另一位數) – Damir

+0

備註:bool實現了一個可用的'ToString',所以'Console 。WriteLine(a == b);'將打印與您的示例中相同的內容。 –

回答

2

NumberDecimalDigits屬性用於與"F""N"標準格式字符串,而不是ToString方法稱爲無格式字符串。

您可以使用:

Console.WriteLine(a.ToString("N", numberFormat)); 
1

試試這個:

Console.WriteLine(String.Format("{0:0.00}", a)); 
Console.WriteLine(String.Format("{0:0.00}", b)); 

輸出將始終小數點後2例。更多的例子在這裏:

http://www.csharp-examples.net/string-format-double/

+0

但它並不總是有小數點分隔符。 – Guffa

+0

無關緊要數字有小數分隔符或不是,輸出將總是有2個小數點。如果你嘗試'Console.WriteLine(String.Format(「{0:0.00}」,10M));'你會看到輸出是'10.00' –

+1

你錯過了這一點。在數字格式中指定的OP小數點分隔符應該是一個句點。如果您未使用數字格式,則小數點分隔符將改爲默認文化中指定的那個。當我嘗試這些代碼時,我發現輸出是'10,00'。 – Guffa

4

如何使它輸出始終已回答了,這個問題,但在這裏就是爲什麼它們輸出不同的擺在首位:

一個decimal值包含在內部,領域一個尺度和一個係數。在10M的情況下,編碼的值具有10的係數和標度爲0:

10M = 10 * 10^0 

10.00M的情況下,編碼的值具有1000的係數,爲2的比例:

10.00M = 1000 * 10^(-2) 

您可以排序的方法通過在內存中的檢查值看到:

unsafe 
{ 
    fixed (decimal* array = new decimal[2]) 
    { 
     array[0] = 10M; 
     array[1] = 10.00M; 
     byte* ptr = (byte*)array; 

     Console.Write("10M: "); 
     for (int i = 0; i < 16; i++) 
      Console.Write(ptr[i].ToString("X2") + " "); 

     Console.WriteLine(""); 

     Console.Write("10.00M: "); 
     for (int i = 16; i < 32; i++) 
      Console.Write(ptr[i].ToString("X2") + " "); 
    } 
} 

輸出

10M: 00 00 00 00 00 00 00 00 0A 00 00 00 00 00 00 00 
10.00M: 00 00 02 00 00 00 00 00 E8 03 00 00 00 00 00 00 

(是0xA是10進制,並了0x3e8是1000十六進制)

此行爲是在C#規範的2.4.4.3節中概述:

的實數由M或後綴m是十進制的類型。例如,文字1m,1.5m,1e10m和123.456M都是十進制類型。該字面值通過採用精確值轉換爲十進制值,並且如有必要,使用銀行家舍入(第4.1.7節)將其舍入到最接近的可表示值。 除非值被舍入或值爲零(在後一種情況下符號和比例將爲0),否則將保留文字中任何明顯的比例。因此,文字2.900米將被解析爲符號0,係數2900和刻度3的小數。

+0

有趣,謝謝你的努力。然而,這解釋了它們的不同之處,並不是ToString爲什麼關心它們在記憶中的表現方式。不應該對原始類型的ToString提供某種類型的保證,提供邏輯上相同的輸入,它會返回相同的輸出?或者這是由設計(ToString的行爲,而不是小數)? – Damir