为啥 C# 中的数字格式字符串在不使用小数 (F0) 时会将数字四舍五入?

Posted

技术标签:

【中文标题】为啥 C# 中的数字格式字符串在不使用小数 (F0) 时会将数字四舍五入?【英文标题】:Why do the numeric format strings in C# round the number when not using decimals (F0)?为什么 C# 中的数字格式字符串在不使用小数 (F0) 时会将数字四舍五入? 【发布时间】:2016-03-05 00:21:26 【问题描述】:

当涉及到 C# 中的标准数字格式字符串时,我遇到了一些非常奇怪的事情。这可能是一个已知的怪癖,但我找不到任何记录它的东西,我无法找到一种方法来真正得到我想要的东西。

我想取一个像 17.929333333333489 这样的数字,并将其格式化为不带小数位。所以我只想要“17”。但是当运行这段代码时。

decimal what = 17.929333333333489m;
Console.WriteLine(what.ToString("F0"));

我得到这个输出

18

查看 Microsoft 的文档,他们的示例显示相同的输出。

https://msdn.microsoft.com/en-us/library/kfsatb94(v=vs.110).aspx

//          F:                     -195489100.84
//          F0:                    -195489101
//          F1:                    -195489100.8
//          F2:                    -195489100.84
//          F3:                    -195489100.838

这是一个显示奇怪问题的代码示例。

http://csharppad.com/gist/d67ddf5d0535c4fe8e39

这个问题不仅限于像“F”和“N”这样的标准问题,还包括像“#”这样的自定义问题。

我怎样才能使用标准的“F0”格式化程序而不是让它围绕我的数字?

【问题讨论】:

【参考方案1】:

来自Standard Numeric Format Strings上的文档:

xx 是一个可选的整数,称为精度说明符。精度说明符的范围从 0 到 99,并影响结果中的位数。请注意,精度说明符控制数字字符串表示中的位数。它不会对数字本身进行四舍五入。要执行舍入操作,请使用Math.CeilingMath.FloorMath.Round 方法。

当精度说明符控制结果字符串中的小数位数时,结果字符串反映从零四舍五入的数字(即使用 MidpointRounding.AwayFromZero)。

因此文档确实讨论了这一点,并且没有明显的方法可以防止纯粹通过格式字符串对输出进行舍入。

我能提供的最好的方法是使用Math.Truncate() 自己截断数字:

decimal what = 17.929333333333489m;
decimal truncatedWhat = Math.Truncate(what);
Console.WriteLine(truncatedWhat.ToString("F0"));

【讨论】:

【参考方案2】:

我相信在最后使用带有“m”的小数会在给定的小数位上四舍五入。

这是我的实验。

decimal what = 17.429333333333489m;
Console.WriteLine(what.ToString("F0"));
Console.WriteLine(what.ToString("N0"));
Console.WriteLine(what.ToString("F1"));
Console.WriteLine(what.ToString("N1"))
17
17
17.4
17.4

如果你想得到 17,我使用了不同的方法,使用 int 和 deciam

double what = 17.929333333333489;
Console.WriteLine(string.Format("0:0", (int)what));
Console.WriteLine(string.Format("0:0", what));
Console.WriteLine(string.Format("0:0.00", Math.Floor(what*100)/100));
Console.WriteLine(string.Format("0:0.00", what));
17
18
17.92
17.93

【讨论】:

以上是关于为啥 C# 中的数字格式字符串在不使用小数 (F0) 时会将数字四舍五入?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不丢失小数的情况下将数据框中的字符转换为数字

C# 怎样把 数字型的字符串 格式化成 两位小数形式的字符串?不足两位小数要补0

为啥 ToString 使用不正确的小数分隔符格式化数字

使用自定义组和小数分隔符将数字格式化为字符串而不更改精度

计算中的小数点为。要么 ,

c#保留小数点后两位怎么做?