浮点数为什么会存在误差?如何解决?

浮点数为什么会有误差?

        static void Main(string[] args)
        {
            float a = 2.9f;
            double b = 1.8;
            Console.WriteLine(a-b);
            

            Console.ReadLine();
        }

输出结果为1.10000009536743

我觉得从计算机的存储原理来解释会好一些,由于计算机只能识别0和1,所以小数也不例外的必须按照二进制来进行储存。

首先我们得清楚小数转换为二进制的方法:对小数点以后的数乘以2,取结果的整数部分(非1即0),然后再用小数部分再乘以2,再取结果的整数部分……以此类推,直到小数部分为0,随后正序排列。

     演示: 0.125 ×2=0.25 .......................0

                 0.25×2=0.5.............................0

                 0.5×2=1.0...............................1

即 0.125的二进制表示为小数部分为0.001

为什么0.1不能被二进制精确的表示出来呢?

 0.1×2=0.2 ......................0

 0.2×2=0.4 ......................0

 0.4×2=0.8 ......................0

扫描二维码关注公众号,回复: 14661472 查看本文章

 0.8×2=1.6.......................1

 0.6×2=1.2.......................1

 0.2×2=0.4.......................0

 .....

于是它的二进制形成了一系列的无限循环小数。

而计算机中存储的位数是有限的,因此当变量存储不了后面的二进制小数时,再转换回十进制就产生误差了。

0.9 十进制转换为二进制是:
0.111001100110011001100…无限循环

所以0.9的表示受精度所限,精度以后的就被忽略了

float时:  十进制保存7位置,二进制保存23位
0.111001100110011001100…转换回十进制就是:
0.89999998

double时:  十进制保存15 ~ 16位,二进制保存52位
0.111001100110011001100…转换回十进制就是:
0.90000000000000002

在使用C#编程的过程中,我暂未发现float受精度所限的情况,貌似会自动取整;但是用double类型时常常会出现精度丢失的问题(除了2的n次以及浮点数加减乘除整数可以准确表示)。 

我们应该如何解决精度丢失呢?

这里我提供两种我较常用的解决办法:1.强制类型转换为float2.用{0:f1}占位符方法限制小数点后位数显示。

1.强制类型转换为float,这个较好理解,以下代码示例

            float  a = 2.9f;
            double b = 1.8;
            Console.WriteLine((float)(a-b));

2.用{0:f1}占位符方法限制小数点后位数显示,这个方法,也较好理解,f1就保留一位小数,f2保留两位,以下代码示例:

            float  a = 2.9f;
            double b = 1.8;
            Console.WriteLine("a-b的值是{0:f1}",a-b);

3.引入Math.Round(a,b)方法(a为变量,b为保留的小数位数),这个方法用于四舍五入,以下代码示例:

            float a = 2.9f;
            double b = 1.8;
            Console.WriteLine(Math.Round(a - b,3));

猜你喜欢

转载自blog.csdn.net/knight209208/article/details/128647230
今日推荐