.NET C#float.Parse将不同的结果返回给double.Parse

Iva*_*sky 6 .net c# floating-point precision types

一些更有经验的人可以解释我今天发现的这个奇怪错误吗?当我用C#脚本加载表数据时,我得到了奇怪的数量.

事实证明问题是类似功能的不同输出:

string amount_in_string = "1234567,15";
double amount_in_double = double.Parse(amount_in_string);
float amount_in_float = float.Parse(amount_in_string);

//amount_in_double = 1234567.15;
//amount_in_float = 1234567.13;
Run Code Online (Sandbox Code Playgroud)

当float和double是相似类型(浮点)时,为什么我会得到这样的结果.精确度可以与这些少量产生差异吗?

Eri*_*hil 6

转换为"1234567.15"时double,结果是可表示的最接近的值double,即1234567.1499999999068677425384521484375.虽然您在问题中报告值为1234567.15,但实际值为1234567.1499999999068677425384521484375.当值以有限的十进制数字显示时,将显示"1234567.15".

转换为"1234567.15"时float,结果是可表示的壁橱值float,即1234567.125.虽然您报告的值为1234567.13,但实际值为1234567.125.当值以有限的十进制数字显示时,可能会显示"1234567.13".


观察到1234567超过1,048,576,即2 20.用于有效数据的float24 位浮点格式(数字的小数部分).如果有效数的高位表示2 20,则低位表示2 20-23 = 2 -3 =⅛.这就是为什么你看到"1234567.15"转换为四舍五入到最接近的第八个值的原因.

  • @MickyD:对于`float`,如上所述,舍入到最近的⅛.对于`double`,舍入到最接近的2 ^(20-52)= 2 ^ -32.进行此舍入的最简单方法是使用`double.Parse`转换数字,然后在小数点后打印32位或更多的十进制数字.(我不知道C#是否能准确地打印出这么多数字.微软并不总能提供良好的转换程序.我使用了Apple的开发工具,它可以准确转换.我使用C:`printf(%.99g \n", 1234567.15);`.)如果想要更详细地查看数学,扩展精度软件可以提供帮助. (2认同)