首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么.Net在String.Format中使用与默认Math.Round()算法不一致的舍入算法?

为什么.Net在String.Format中使用与默认Math.Round()算法不一致的舍入算法?
EN

Stack Overflow用户
提问于 2010-02-09 09:12:50
回答 4查看 7.4K关注 0票数 28

我注意到C#/.NET中有以下不一致之处,我想知道为什么会这样。

代码语言:javascript
复制
Console.WriteLine("{0,-4:#.0} | {1,-4:#.0}", 1.04, Math.Round(1.04, 1));
Console.WriteLine("{0,-4:#.0} | {1,-4:#.0}", 1.05, Math.Round(1.05, 1));
Console.WriteLine("{0,-4:#.0} | {1,-4:#.0}", 1.06, Math.Round(1.06, 1));
Console.WriteLine("{0,-4:#.0} | {1,-4:#.0}", 1.14, Math.Round(1.14, 1));
Console.WriteLine("{0,-4:#.0} | {1,-4:#.0}", 1.15, Math.Round(1.15, 1));
Console.WriteLine("{0,-4:#.0} | {1,-4:#.0}", 1.16, Math.Round(1.16, 1));
Console.WriteLine();
Console.WriteLine("{0,-4:#.0} | {1,-4:#.0}", 1.04, Math.Round(1.04, 1, MidpointRounding.AwayFromZero));
Console.WriteLine("{0,-4:#.0} | {1,-4:#.0}", 1.05, Math.Round(1.05, 1, MidpointRounding.AwayFromZero));
Console.WriteLine("{0,-4:#.0} | {1,-4:#.0}", 1.06, Math.Round(1.06, 1, MidpointRounding.AwayFromZero));
Console.WriteLine("{0,-4:#.0} | {1,-4:#.0}", 1.14, Math.Round(1.14, 1, MidpointRounding.AwayFromZero));
Console.WriteLine("{0,-4:#.0} | {1,-4:#.0}", 1.15, Math.Round(1.15, 1, MidpointRounding.AwayFromZero));
Console.WriteLine("{0,-4:#.0} | {1,-4:#.0}", 1.16, Math.Round(1.16, 1, MidpointRounding.AwayFromZero));

输出:

代码语言:javascript
复制
1.0  | 1.0
1.1  | 1.0
1.1  | 1.1
1.1  | 1.1
1.2  | 1.2
1.2  | 1.2

1.0  | 1.0
1.1  | 1.1
1.1  | 1.1
1.1  | 1.1
1.2  | 1.2
1.2  | 1.2

看起来默认的字符串格式化行为是使用MidpointRounding.AwayFromZero而不是Math.Round()的默认MidpointRounding.ToEven进行舍入。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2010-02-09 14:45:10

作为一个历史记录,最初的Visual Basic实现的Format$也与四舍五入,也就是银行家的舍入不一致。原始格式$ code是由Tim Paterson编写的。您可能还记得,Tim是一个名为QDOS (后来称为MS-DOS)的小程序的作者,在那里有一段时间是相当畅销的。

也许这是25年来向后兼容的又一案例。

票数 12
EN

Stack Overflow用户

发布于 2015-01-21 22:28:39

看起来这个问题比“简单的”不一致更糟糕:

代码语言:javascript
复制
double dd = 0.034999999999999996;

Math.Round(dd, 2); // 0.03
Math.Round(dd, 2, MidpointRounding.AwayFromZero); // 0.03
Math.Round(dd, 2, MidpointRounding.ToEven); // 0.03

string.Format("{0:N2}", dd); // "0.04"

这简直是胡说八道。谁知道它是从哪里弄来的"0.04“。

票数 3
EN

Stack Overflow用户

发布于 2010-02-09 09:31:41

请看这里:Possible Bug: Math.Round returning inconsistent results

WriteLine()只是调用Object.ToString(),这最终导致对Number.FormatDouble(this,null,NumberFormatInfo.CurrentInfo)的调用。如您所见,格式字符串的参数为null。如果想要从ToString()获得真正的东西,就必须使用System.Diagnostics.Debug.WriteLine(n.ToString("R")).

“使用此说明符设置单值或双精度值的格式时,首先使用常规格式对其进行测试,双精度为15位精度,单精度为7位精度。如果该值成功解析回相同的数值,则使用常规格式说明符进行格式化。如果该值未成功解析回相同的数值,则使用17位精度的双精度位和9位单精度位的精度进行格式化。”Standard Numeric Format Strings

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2226081

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档