为的ToString奇数小数类型的行为(的IFormatProvider)(Odd decimal

2019-08-03 20:46发布

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 10真

它为什么不一样? 更重要的是,我怎么调用toString(),以确保相同的输出,无论变量如何初始化?

Answer 1:

所述NumberDecimalDigits属性用于与"F""N"的标准格式字符串,而不是ToString方法称为无格式字符串。

您可以使用:

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


Answer 2:

如何使它输出始终已回答了,但这里的问题是,为什么他们不同的输出摆在首位:

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后缀是decimal类型。 例如,文字1M,1.5M,1e10m,和123.456M都是十进制类型。 此实数通过取精确值使用银行家的舍入转换为十进制值,并且,如有必要,四舍五入到最接近的表示值(§4.1.7)。 任何规模的字面表观保留除非值被四舍五入或值为零(在该后者的情况下的符号和规模将是0)。 因此,文字2.900米将被解析,以形成具有符号0,系数2900,和标度3小数。



Answer 3:

试试这个:

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/



文章来源: Odd decimal type behavior for ToString(IFormatProvider)