简而言之,我想知道为什么下面的ToString()行不符合我的期望。
float actual = 111253.469F;
double rounded = Math.Round(actual, 2); // 111253.47 (expected)
string stringified = actual.ToString(); // 111253.50 (expected 111253.469)
string currency = actual.ToString("C"); // $111253.50 (expected 111253.47 or possibly .46)
有人可以解释发生了什么吗?
注意: 根据浮点数的其他问题,我不认为浮点值是精确的。但是我确实希望字符串输出反映有问题的浮点数的字符串值。
在这种情况下,如果我设置一个断点并在快速监视中查看“实际”的值,它不会显示“111253.5”,它会显示“111253.469”。我不明白为什么打印时不会出现这种情况。特别是在货币情况下,我希望它能够舍入到适当的小数点然后显示,而不是选择其他一些字面值。这不是一个数学问题,它是一个ToString()行为问题。
编辑:
根据下面的每个Quantic的评论,ToString
默认使用G
格式,将数字限制为7位有效数字,从而导致数字在此处显示。
答案 0 :(得分:1)
根据MSDN about Single.ToString()(强调我的):
默认情况下,返回值仅包含7位精度,但内部最多保留9位数。如果此实例的值大于7位,则M:System.Single.ToString(System.String)返回P:System.Globalization.NumberFormatInfo.PositiveInfinitySymbol或P:System.Globalization.NumberFormatInfo.NegativeInfinitySymbol而不是预期的数字。 如果您需要更高的精度,请指定格式为“G9”格式规范(始终返回9位精度)或“R”,如果数字可以用该精度表示,则返回7位数,如果是,则返回9位数数字只能以最大精度表示。
因此,您的代码示例的行为完全符合记录:
ToString()
将使用"G"
,这将使用7位精度ToString("C")
也将使用7位精度 "R"
和"G9"
都会返回111253.469
,"G8"
会返回111253.47
。
答案 1 :(得分:0)
您没有 ToString()问题,您有浮动问题。
float
是一个浮点值,根据定义,它具有7位数的精度:MSDN
现在,您有超过7个数字:float actual = 111253.469F
,因此系统会对最不重要的数字进行舍入,并且您的操作会获得 111253.5 。
请注意, double 是正确计算的,因为它可以处理超过7位有效数字。