当使用小数时,为什么使用Console.Write时,double的小数部分没有显示?

Nit*_*wal 0 c#

请考虑以下代码:

decimal decimalVal = 4.00M;

double doubleVal = 5.00;

Console.Write(decimalVal);

Console.Write(doubleVal);
Run Code Online (Sandbox Code Playgroud)

为什么decimalVal显示小数点后的零,但小数点后的那些doubleVal不是?

Gra*_*ICA 6

你看到的差异是由于Console.Write()设计的原因.

当你这样打电话时Console.Write:

 Console.Write(decimalVal);

 Console.Write(doubleVal);
Run Code Online (Sandbox Code Playgroud)

在幕后,它实际上是在调用ToString()并传递你当前的文化,相当于:

 Console.Write(decimalVal.ToString(Thread.CurrentThread.CurrentCulture));

 Console.Write(doubleVal.ToString(Thread.CurrentThread.CurrentCulture));
Run Code Online (Sandbox Code Playgroud)

这两行没有指定格式,因此使用了您的文化的一般("G")格式,如Double.ToString()和文档中所述Decimal.ToString().

 Console.Write(decimalVal.ToString("G"));

 Console.Write(doubleVal.ToString("G"));
Run Code Online (Sandbox Code Playgroud)

那么"G"格式说明符的输出是什么?再次,从文档:

如果需要,结果包含小数点,并且省略小数点后的尾随零.如果存在精度说明符且结果中的有效位数超过指定的精度,则通过舍入删除多余的尾随数字.

但是,如果数字是十进制并且省略精度说明符...则保留尾随零.

(我的重点补充)

所以最终的结果就是Console.Write()产出......

  • 你的double没有尾随零.

  • 你的decimal价值尾随零.

起初,我将差异归结为"开发人员的选择",但随后雷蒙德·陈和杰夫·梅尔卡多都评论了其根本原因:

这是因为十进制会记住它有多少精度.4.00M和4.0M不一样.(虽然他们比较相等.)转换为字符串显示精度.Double不跟踪精度.〜雷蒙德

decimal 必须保持它所代表的值的精度.double没有.当您定义一个带有3位有效数字的小数"4"时,这正是您得到的.double 5.00可以用精确值表示5.它有多少小数位没有编码到值中.〜杰夫

另外,从Decimal文档:

缩放因子还保留十进制数中的任何尾随零.尾随零不会影响算术或比较运算中的十进制数的值.但是,如果应用了适当的格式字符串,ToString方法可能会显示尾随零.

(" 比例因子 "是表示小数点的小数部分的值 - 小数点后的部分.)

这意味着,虽然3.0m,3.00m和3.000000m在比较它们时都被认为是相等的,但是Decimal类型存储了适当的比例因子以确保尾随零没有丢失.

这不适用于Double未保留前导零的类型.虽然,如果你有一个double并且想要确保至少显示几个零,你可以指定一种格式:

Console.Write(doubleVal.ToString("F2"));  // outputs 5.00
Run Code Online (Sandbox Code Playgroud)