浮点数数据误差eps处理(详细解析)

众所周知,C和C++中,经常用到的浮点数类型无论是float类型还是double类型都存在一定的精度与误差,关于float与double所表示的范围如下:
这里写图片描述
double的精度足够日常使用,但是浮点数在计算机内部存储的时候存在的误差值是不可避免的,比如说数字5在计算机中存储的数据根据运算方式的不同,结果可能是4.99999999998,也可能是5.0000000001,这在我们需要对浮点数进行一些特定的操作的时候,非常容易出现不必要的麻烦,比如我们需要对浮点数double n=3.8进行如下操作的时候:

取n的整数部分可以用:int a = int(n);
得到n的小数部分: double b = n - a;
对小数部分进行操作:b *= 10;
取b的整数部分可以用: int c = int(b);

对于以上操作,按照正确的逻辑,取3.8的整数部分3,再用3.8 - 3 = 0.8,然后0.8 * 10 = 8,取8的整数部分得8.但是程序的输出结果显然不想我们想象的那么简单:

int main()
{
    double n;
    while(cin>>n)
    {
        double ans = n - int(n);
        ans *= 10;
        int ans1 = int(ans);
        printf("       ans = %d\n", ans1);
    }
    return 0;
 }

对于以上代码,如果输入3.8,输出结果为:
这里写图片描述

很显然结果为7,下面添加几句代码来验证一下:

int main()
{
    double n;
    while(cin>>n)
    {
            double ans = n - int(n);
            printf("       ans = %.20lf\n", ans);
            ans *= 10;
            printf("       ans = %.20lf\n", ans);
            int ans1 = int(ans);
            printf("       ans1 = %d\n", ans1);
    }
    return 0;
 }

这里写图片描述
很容易发现,第一个ans取得是3.8的小数部分,结果是0.79999999999999982000,正确的结果显然应该是0.8,但是由于浮点数在计算机中存储的特性,计算机认为0.79999999999999982000就是0.8,显然这给后续的运算已经产生了不必要的影响,那么如何处理呢?下面来介绍eps的处理方法:

eps处理浮点数误差的问题:

何为eps
eps可以看成是epsilon的缩写,可以用来表示一个无穷小的量,通常取eps的值为:1e-10~1e-8 之间。
可以做什么?
对于数字5,如果计算机存储的数据为5.000000000000001,显然对这种情况不需要用到eps进行补偿,而对于有缺省的类似于4.9999999999999998的数据,eps可以进行对它的缺省值进行一定的补偿,使其在计算机中的存储值变成5.00000000000000或者5.000000000000001,这样在后续的计算中就会解决因为存储的误差造成的不必要后果。下面同样用代码验证一下:

#define eps 1e-10 //宏定义eps为1e-10
int main()
{
    double n;
    while(cin>>n)
    {
        double ans = n - int(n);
        ans *= 10;
        int ans1 = int(ans + eps);
        printf("       ans1 = %d\n", ans1);
    }
    return 0;
 }

输出结果为:
**输出结果**

结果一面了然。另外,对于负数的情况,只需要把ans + eps改为ans - eps即可,下面附上完整代码:

#include<iostream>
#include<cstdio>
#define eps 1e-10
using namespace std;
int main()
{
    double n;
    while(cin>>n)
    {
        double ans = n - int(n);
        ans *= 10;
        int ans1;
        if(ans > 0)
            ans1 = int(ans + eps);
        else
            ans1 = int(ans - eps);//如果ans < 0, 要用ans - eps;
        printf("       ans1 = %d\n", ans1);
    }
    return 0;
}

输出结果:
这里写图片描述
总结:
以上内容部分参考网上资料,以及结合平时的做题经历,如有不妥,欢迎批评指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值