浮动计算错误

时间:2013-03-15 10:07:01

标签: c#

结果必须是806603.77,但为什么我得到806603.8?

float a = 855000.00f;
float b = 48396.23f;

float res = a - b;
Console.WriteLine(res);
Console.ReadKey();

4 个答案:

答案 0 :(得分:3)

float(也称为System.Single)的精确度相当于小数。您的res差异需要八个有效十进制数字。因此,预计float中的精度不够。

此外:

一些额外信息:接近806,000(806千),float只剩下四位小数部分。因此对于res,它必须在

之间进行选择
806603 + 12/16 == 806603.75000000, and
806603 + 13/16 == 806603.81250000

它选择第一个,因为它最接近理想结果。但是,在调用"806603.8"ToString()调用时)时,这两个值都会输出为Console.WriteLine(float)。通用ToString调用最多显示7个有效小数。要显示两个浮点数是不同的,即使它们使用标准格式打印相同,请使用格式字符串"R",例如

Console.WriteLine(res.ToString("R"));

答案 1 :(得分:3)

您应该使用decimal,因为float只有32-bit 7位 精度,这就是结果不同的原因,另一方面,decimal具有128-bit 28-29位数 精度。

decimal a = 855000.00M;
decimal b = 48396.23M;

decimal res = a - b;
Console.WriteLine(res);
Console.ReadKey();

输出:806603.77

答案 2 :(得分:1)

因为float精度有限(32位)。如果您想要更高精度,请使用doubledecimal

答案 3 :(得分:0)

请注意,盲目地使用Decimal还不够好。

阅读Oded发布的链接:What Every Computer Scientist Should Know About Floating-Point Arithmetic

只有然后决定使用的相应数字类型。

不要陷入认为只使用Decimal会给你精确结果的陷阱;它不会永远。

请考虑以下代码:

Decimal d1 = 1;
Decimal d2 = 101;
Decimal d3 = d1/d2;
Decimal d4 = d3*d2; // d4 = (d1/d2) * d2 = d1

if (d4 == d1)
{
    Console.WriteLine("Yay!");
}
else
{
    Console.WriteLine("Urk!");
}

如果十进制计算是准确的,那么该代码应该打印“Yay!”因为d1应该与d4相同,对吧?

嗯,事实并非如此。

另请注意,十进制计算比双重计算慢几千倍。它们并不总是适用于非货币计算(例如计算像素偏移或物理事物,如速度,或任何涉及超越数字等等)。