浮点类型float和double有一些特殊性,比如他们处理精度的方式,在比较两个值是否相等时,浮点类型的不准确性可能会造成非常严重的后果。有时候本来应该是相等值,最后一比较却别的不想等了。
一次很简单的赋值可能就会将引发精度问题,比如double number=140.6F。由于double能容纳的比float更加精确的值,所以C#编译器实际上会将这个表达式解释成double number=140.600 0061 0351 6。而这个值作为一个float确实是140.6,但表示成一个double的时候,并不能准确度地等于140.6
static void TestMethod1() { decimal decimalnumber = 4.2M; double doubleNumber1 = 0.1F * 42F; double doubleNumber2 = 0.1D * 42D; double floatNumbler = 0.1F * 42F; Trace.Assert(decimalnumber !=( decimal)doubleNumber1); Trace.Assert(( double)decimalnumber != doubleNumber1); Trace.Assert(( float)decimalnumber != floatNumbler); Trace.Assert( 4.2F != 4.2D); }
为了避免浮点类型的不准确性而造成的非预期的结果,开发者应该避免使用这些类型来构建相等性条件。相反,相等性条件应该包含一个容差,为此,一个简单的办法就是用一个值减去另一个值,然后计算结果的绝对值是否小于最大容差。另外,更好的方案是使用decimal类型,而不是浮点类型。
另外,浮点类型还有其他的一些特殊性质,例如,一个整数除以零理论上应该是错误的。这对于精确类型的Int,decimal这一点都是成立的。然而对于浮点类型float和double允许一些特殊值,例如:
float f=0f;
System.Console.Write(f/0);