float,double,decimal彼此转换会出现的精度问题(今天你Bug了吗

在一开始先说明下,此处的精度问题并不包含数字过大、强转溢出之类导致的问题,主要说明三者之间比较或计算时容易产生的精度问题,以避免开发中莫名其妙的数据问题。大学时学的是C语言,虽然就没学会过,但对于float和double的描述还是记的很清楚,float和double因为采用科学记数法,会出现精度问题,要比较的话,应该是用两个的差值,取绝对值,如果该值小于某个数,你就可以认为两个数字是相等的,比如下面的写法

if (Math.Abs(1.01f – 1.01d) < 0.001){ //相等}而下面这个是永远不会为trueif (1.01f == 1.01f){ //永远都不可能进入此块区域}结果在C#里上面的==比较返回结果却是True,而且声明了1.01f,直接用的时候,还是1.01,居然没变!(这里不知道我是不是记错了,也不可能在找C来尝试了)然后在(double)1.01f时,输出却不是1.01了,所以在这里做了一个完整的测试,输出结果直接备注在了后面(不同电脑上的精度值可能有所不同)float x = 100.1f;double y = 100.1d;decimal z = 100.1m;Console.WriteLine("X:" + x + " Y:" + y + " Z:" + z);//X:100.1 Y:100.1 Z:100.1Console.WriteLine("Double X:" + (double)x + " Float Y:" + (float)y + " Double Z:" + (double)z + " Float Z:" + (float)z);//Double X:100.099998474121 Float Y:100.1 Double Z:100.1 Float Z:100.1Console.WriteLine("Float To Double To Float: " + (float)((double)x));//Float To Double To Float: 100.1Console.WriteLine("Double To Float To Double: " + (double)((float)y)); //Double To Float To Double: 100.099998474121Console.WriteLine("(Decimal)Float Equals (Decimal)Double: " + ((decimal)x == (decimal)y));//(Decimal)Float Equals (Decimal)Double: TrueConsole.WriteLine("(Double)Decimal Equals (Float)Decimal: " + ((double)z == (float)z));//(Double)Decimal Equals (Float)Decimal: FalseConsole.WriteLine("Double Equals Float: " + (x == y));//Double Equals Float: FalseConsole.WriteLine("Double Equals Float Transfer: " + ((double)x == y));//Double Equals Float Transfer: FalseConsole.WriteLine("Float Equals Double Transfer: " + (x == (float)y));//Double Equals Float Transfer: TrueConsole.WriteLine("Float Equals Decimal Transfer: " + (x == (float)z));//Float Equals Decimal Transfer: TrueConsole.WriteLine("Double Equals Decimal Transfer: " + (y == (double)z));//Double Equals Decimal Transfer: Truevar a = 100.111d * x;var b = 100.111d * y;var c = 100.111d * y;var d = 100.111f * x;var e = 100.111f * x;Console.WriteLine("A:" + a + " B:" + b + " C:" + c + " D:" + d + " E:" + e);//A:10021.1109472427 B:10021.1111 C:10021.1111 D:10021.11 E:10021.11Console.WriteLine("Double*Float Equals Double*Double: " + (a == b));//Double*Float Equals Double*Double: FalseConsole.WriteLine("Double*Double Equals Double*Double: " + (b == c));//Double*Float Equals Double*Double: TrueConsole.WriteLine("Float*Float Equals Float*Float: " + (e == d));//Double*Float Equals Double*Double: TrueConsole.WriteLine("Double*Double Equals Float*Float: " + (b == d));//Double*Float Equals Double*Double: False

在上面的例子中同时对float、double、decimal做了彼此之间的转化与输出,在这三个类型中,彼此之间允许从低向高进行隐式转换是:float–>double ,从高向低必须显式转换(备注:float和double不能隐式转换成decimal,必须显式转换)

C#默认实现了隐式转换功能,所以float==double判断与(double)float==double其实是一致的,同样的情况会出现在加减乘除等地方,但通过上面的demo,可以很明确的得到结论:

1、相同类型的数字进行比较,不存在隐式转换,,值也就不会变化,所以可以得到True的结果

2、如果类型不同进行比较时,float转double会出现精度丢失,但double转float不会出现精度丢失(甚至会补上精度,神奇的(float)((double)x)结果还是100.1)

3、float–>decimal,double–>decimal不会出现精度问题,反过来也不会出现精度问题

所以骚年,请不要在程序里面直接进行float==double的比较,这看起来一样的数字,结果一定会是false,如果你真要进行比较,请都强转成decimal或者将double强转成float再进行比较

涉水而过的声音此次想起,

float,double,decimal彼此转换会出现的精度问题(今天你Bug了吗

相关文章:

你感兴趣的文章:

标签云: