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

时间:2018-08-23 14:44:43

标签: c# .net types floating-point precision

一些经验丰富的人可以解释我今天发现的这个奇怪的错误吗? 当我用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;

当float和double是相似的类型(浮点)时,为什么会得到不同的结果。像这样少量的精度可以有所作为吗?

3 个答案:

答案 0 :(得分: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 float使用的32位浮点格式使用24位作为有效数字(数字的小数部分)。如果有效数的高位表示2 20 ,则低位表示2 20-23 = 2 -3 =⅛。这就是为什么您看到“ 1234567.15”转换为四舍五入到最接近的八分之一的值的原因。

答案 1 :(得分:2)

浮点数从不精确,它们是数字的表示形式。常用的例子是

1/3 + 1/3 = 2/3

...因此,浮点数.33333 + .33333中的答案不是精确的2/3,而是.66666

长话短说,您无法转换为精确二进制数的更精确分数始终会有一个舍入数字。越精确,发生舍入误差的可能性就越大。

请记住,如果您执行多个不同的分数运算,您甚至可能会遇到多个不同的舍入错误,这些错误会使数字意外正确,甚至更进一步。

答案 2 :(得分:-1)

您可以看到结果的小提琴(这里也有文化问题)

https://dotnetfiddle.net/Lnv1q7

    string amount_in_string = "1234567,15"; // NOTE THE COMMA in original
    string amount_in_string = "1234567.15"; //my correct culture
    double amount_in_double = double.Parse(amount_in_string);
    float amount_in_float = float.Parse(amount_in_string);

    Console.WriteLine(amount_in_string);
    Console.WriteLine(amount_in_double);
    Console.WriteLine(amount_in_float);

结果(分析错误的语言!)

1234567,15
123456715
1.234567E+08

结果(解析正确的文化!)

1234567.15
1234567.15
1234567

另一种用float证明精度下降的

float flt = 1F/3;
double dbl = 1D/3;
decimal dcm = 1M/3;
Console.WriteLine("float: {0} double: {1} decimal: {2}", flt, dbl, dcm);

结果

float: 0.3333333  
double: 0.333333333333333  
decimal: 0.3333333333333333333333333333

浮点数仅应在某些精度损失不是非常有价值的情况下使用。这是因为浮点数是32位,十进制是128位 浮点数主要用在像素坐标中,精度的损失并不重要,因为消费者可以通过任何方式将位置转换为更精确的坐标。

除非您不关心(某些)精度的损失,否则应积极避免.NET浮动中的

。除非您正在编写游戏,否则现在可​​能永远不会这样

这是银行业务问题的根源,当交易损失一分钱/分的百分之一/美分时,每笔交易看似看不见,但却导致大量“丢失”钱。

使用十进制