为什么双精度的小数部分不显示 Console.Write,而它与小数一起显示

本文关键字:显示 一起 小数 Write Console 双精度 小数部 为什么 | 更新日期: 2023-09-27 18:37:22

请考虑以下代码:

decimal decimalVal = 4.00M;
double doubleVal = 5.00;
Console.Write(decimalVal);
Console.Write(doubleVal);

为什么decimalVal小数点后面显示零,而doubleVal小数点后面的零不显示?

为什么双精度的小数部分不显示 Console.Write,而它与小数一起显示

您看到的差异是由于Console.Write()的设计方式。

当你这样称呼Console.Write时:

 Console.Write(decimalVal);
 Console.Write(doubleVal);

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

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

这两行未指定格式,因此使用区域性的常规 ("G") 格式,如 Double.ToString()Decimal.ToString() 的文档中所述。

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

那么"G"格式说明符输出什么?同样,从文档中:

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

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

(我的强调是加的)

所以最终结果是Console.Write()输出...

  • 您的double,不带尾随零。

  • 带有尾随零decimal值。

起初,我把差异归结

为"开发者的选择",但后来Raymond Chen和Jeff Mercado都评论了根本原因:

这是因为十进制会记住它有多少精度。 4.00M 和 4.0M 是不一样的。(尽管它们比较相等。转换为字符串可显示精度。双精度不跟踪精度。~雷蒙德

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

此外,从十进制文档中:

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

("比例因子"是一个值,表示小数点的小数部分 - 小数点之后的部分。

这意味着,尽管 3.0m、3.00m 和 3.000000m 在比较时都被认为是相等的,但 Decimal 类型存储适当的比例因子以确保尾随零不会丢失。

这不适用于不保留前导零的Double类型。但是,如果您有double并希望确保至少显示几个零,则可以指定一种格式:

Console.Write(doubleVal.ToString("F2"));  // outputs 5.00