zoukankan      html  css  js  c++  java
  • 浮点数的运算精度丢失

    引出

    打开Python编译器,输入 0.1+0.2, 期待的结果是0.3,但是输出为:

    0.30000000000000004

    有点小尴尬,这是为什么呢?

    解惑

    其实这设计到了计算机的浮点数存储是以二进制进行存储的。

    说二进制不太形象,换成我们最长使用的十进制和分数

    1/5,使用小数表示为0.2,但是1/3,使用小数表示就是一个无限循环小数:0.3333333, 也就是说,分数的 1/3+1/3=2/3,但如果使用小数:0.3333+0.3333=0.6666, 结果只会无限接近2/3,而不会等于2/3

    因为把10分成三份,是不能够整分的。同样,把2分成十份,也不能整分。考虑到2整分只能分成两份,也就是说,二进制只能精确表示十进制小数0.5

    十进制到二进制的转换在此略过。

    十进制的0.1,转换成二进制是:0.00011001100110011无限循环的小数,所以二进制的小数运算,就会出现上面的1/3+1/3的情况,无法精确计算,只能够近似表示。那为什么python这些语言,我们在使用的时候没有察觉到这个问题呢?因为编译器自觉的帮我们做了近似的处理。

    和十进制无法精确表示分数的1/3同样,二进制也无法精确表示十进制的小数。

    分析

    为了方便分析,我们讲计算机存储的字节数量进行缩减,我们假设小数点后只能保存8为小数。

    十进制的0.1,转换成二进制为:0.00011001 (再反转回十进制,就会发现精度的丢失了,十进制是:0.09765625)

    十进制的0.2,转换成二进制为:0.00110011 (反转回十进制,为:0.19921875)

    加法运算:

    十进制

    0.1+0.2=0.3

    二进制

    0.00011001+0.00110011=0.01001100 (转成十进制:0.296875)


    当然,计算机中存储的位数要比8位多,python浮点数占用8个字节,64位。但因为是无限小数,并不是位数多了就会准确。

    那么如何做这种精度的计算呢?其实很简单,精度丢失是小数才会有,只要转成整数,就不会有这个问题了。比如Python中:

    (1.0+2.0)/10

    结果:0.3, 没毛病。

    当然,这个0.3也不是精确的0.3,但会在显示过程进行精度转换,通过整数运算,避免了小数运算过程中的丢失精度问题。

  • 相关阅读:
    洛谷P1033 自由落体 题解
    尴尬
    UVA11988 【Broken Keyboard (a.k.a. Beiju Text)】:题解
    UVA101 The Blocks Problem 题解
    TCP的粘包和拆包问题及解决办法(C#)
    MIPS学习笔记(一)
    MySQL基础(一)
    博客园的标签怎么变了两下???
    nextInt()和nextLine()连用报错
    C++代码雨
  • 原文地址:https://www.cnblogs.com/hujingnb/p/11748220.html
Copyright © 2011-2022 走看看