[ Python ] print(0.3 == (3 * 0.1)) ->False why? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
Leigg
V2EX    Python

[ Python ] print(0.3 == (3 * 0.1)) ->False why?

  •  
  •   Leigg 2018-06-14 15:11:40 +08:00 9238 次点击
    这是一个创建于 2684 天前的主题,其中的信息可能已经有所发展或是发生改变。

    转换为:
    3*0.1 = 0.30000000000000004
    为啥捏?

    第 1 条附言    2018-06-14 23:17:47 +08:00
    看到有蛮多人收藏,“感谢”,说明还是有不少人对这个现象的原理有点模糊的。
    简单总结一下,评论中 @nasmatic 给出的 python 官网解释是比较容易理解的,链接是这个:
    https://docs.python.org/2/tutorial/floatingpoint.html
    还是感谢其他朋友的帮助,谢谢!
    (对于几个阴阳怪气的评论也不想说过多,你明白这个我认为你 ok 啊,你愿意帮我就好好回复不行吗?不愿意就拉倒呗
    但是你怎么就会有一种优越感呢?你是认为我会的东西你都会是吗?大家都是普通人怎么就不能好好说话呢。。不喜勿喷)
    45 条回复    2020-10-30 14:12:42 +08:00
    broadliyn
        1
    broadliyn  
       2018-06-14 15:16:02 +08:00   7
    这类问题简直就是 v2 大姨妈一样。。。
    请 lz 去补习一下,计算机系统原理,原码、补码、反码、定点数、浮点数相关的章节。
    SuperMild
        2
    SuperMild  
       2018-06-14 15:24:53 +08:00 via iPhone
    重点补习一下搜索技能
    nasmatic
      &nsp; 3
    nasmatic  
       2018-06-14 15:26:23 +08:00
    Leigg
        4
    Leigg  
    OP
       2018-06-14 16:12:18 +08:00
    @nasmatic 谢谢。

    @SuperMild 就是不知道咋搜啊
    crayygy
        5
    crayygy  
       2018-06-14 16:14:14 +08:00 via iPhone
    IEEE754
    Leigg
        6
    Leigg  
    OP
       2018-06-14 16:16:12 +08:00
    @broadliyn 老哥担待一下,我也不是大佬,啥都懂,总有知识缺口。
    rabbbit
        7
    rabbbit  
       2018-06-14 16:18:06 +08:00
    看这个 t/448774
    kingname
        8
    kingname  
       2018-06-14 16:22:10 +08:00   15
    0.3 转换为二进制:
    0.3 * 2 = 0.6 -> 0
    0.6 * 2 = 1.2 -> 1
    0.2 * 2 = 0.4 -> 0
    0.4 * 0.2 = 0.8 -> 0
    0.8 * 2 = 1.6 -> 1
    0.6 * 2 = 1.2 -> 1
    如此循环

    所以 0.3 对应的二进制数为 0.01001100110011001 ……无限循环下去。

    而电脑会把这个无限循环的东西截断为:0.0100110011001100110011001100110011001100110011001101

    这个截断以后的二进制再转换回十进制,就变成了 0.30000000000000004
    ihancheng
        9
    ihancheng  
       2018-06-14 16:23:20 +08:00 via Android
    离散数学了解下?
    cuzfinal
        10
    cuzfinal  
       2018-06-14 16:53:05 +08:00   12
    zynlp
        11
    zynlp  
       2018-06-14 16:54:41 +08:00 via iPhone
    加个 round
    araraloren
        12
    araraloren  
       2018-06-14 16:55:12 +08:00
    IEEE754 实现的浮点就是这样的,有的语言有支持无限精度的浮点数,比如

    #!/usr/bin/perl6
    # your code goes here

    # default is Rat
    say 0.333.WHAT;
    say 0.2222 - 0.22 - 0.0005;
    say 0.2222 - 0.22 - 0.0005 == 0.0017;

    # Num is IEEE754 number
    say 0.255.Num.WHAT;
    say 0.2222.Num - 0.22.Num - 0.0005.Num;

    have a try: https://ideone.com/CckupN
    jmc891205
        13
    jmc891205  
       2018-06-14 17:08:40 +08:00
    永远不要用==去比较浮点数
    suilin
        14
    suilin  
       2018-06-14 17:43:01 +08:00
    几位大佬包容下嘛(手动狗头
    robinlovemaggie
        15
    robinlovemaggie  
       2018-06-14 17:44:09 +08:00
    打个比方:你把一个蛋糕切成三块再拼到一起,它还是一个蛋糕吗?
    SingeeKing
        16
    SingeeKing  
    PRO
       2018-06-14 17:45:55 +08:00
    涉及浮点数判断请使用 round

    0.3 == round(3 * 0.1, 2)
    robinlovemaggie
        17
    robinlovemaggie  
       2018-06-14 18:01:25 +08:00   1
    ipwx
        18
    ipwx  
       2018-06-14 18:27:49 +08:00 via iPhone
    十进制的准确值换算成二进制可能就要写无穷多位… 比如 1/10=1/16+1/32+1/256+1/512+…,所以对应二进制就是 0.00011001100110011 …
    Allianzcortex
        19
    Allianzcortex  
       2018-06-14 21:02:37 +08:00   2
    Raymon111111
        20
    Raymon111111  
       2018-06-14 21:45:21 +08:00   1
    科班出身真的挺重要的
    Leigg
        21
    Leigg  
    OP
       2018-06-14 21:54:34 +08:00 via iPhone
    @Raymon111111 哥们,我不反驳你,但你这句话对我说真没什么意思。科班不科班出身对一个人确实有不小的影响,但这点影响从长远来看真算不了什么,一个人他 /她行结果就一定不会差,但倘若他 /她不行富二代最终也是个只会吃喝玩的废物。
    mingyun
        22
    mingyun  
       2018-06-14 21:54:41 +08:00
    不少语言这样的
    a22271001
        23
    a22271001  
       2018-06-14 21:59:34 +08:00 via Android
    @ihancheng 这个跟离散数学有什么关系?
    andylsr
        24
    andylsr  
       2018-06-14 22:07:59 +08:00 via Android
    @jmc891205 永远不要用浮点数┑( ̄Д  ̄)┍
    Leigg
        25
    Leigg  
    OP
       2018-06-14 22:19:36 +08:00
    @cuzfinal nice !
    iceheart
        26
    iceheart  
       2018-06-14 22:28:26 +08:00 via Android
    不是每个编程语言都这样的。
    qile1
        27
    qile1  
       2018-06-14 22:54:16 +08:00 via Android
    @andylsr 那是不是如果保留两位就 if int ( 0.3*100 )==int ( 3*0.1*100 ):
    andylsr
        28
    andylsr  
       2018-06-14 23:01:14 +08:00 via Android
    @qile1 这个题~这么搞其实没啥意思啦~类型转换总能带来意想不到的 bug~反正说自己实际应用中能不用就不用~~
    yanhejihe
        29
    yanhejihe  
       2018-06-14 23:27:02 +08:00
    从 Java 就被虐过,还好 Java 有 bigdecimal 可以用。
    incompatible
        30
    incompatible  
       2018-06-15 00:22:47 +08:00
    @ihancheng 你确定你学过离散数学?这跟离散数学有什么关系??
    lonccc
        31
    lonccc  
       2018-06-15 00:44:52 +08:00 via Android   1
    @Leigg 是的,科班出身不能决定什么,搜索和学习能力可能更重要。楼主还是应该想想为啥自己不知道咋搜呢。这个问题对于大一正常上过 c 语言的人来说应该都遇到过吧,不说知道具体原因,但也知道浮点数精度有限,不能用等于来判断,所以也怪不得大家语气不善了。
    ericls
        32
    ericls  
       2018-06-15 00:53:20 +08:00 via iPhone
    不对吧 print 应该返回 None 才对
    ericls
        33
    ericls  
       2018-06-15 00:56:57 +08:00 via iPhone
    @Raymon111111 不同意 最多从概率上来讲 科班出身的懂这个的可能性大

    重要的是学不学 而不是在哪里学

    Disclaimer: 我是非科班出生
    dangyuluo
        34
    dangyuluo  
       2018-06-15 01:22:13 +08:00
    以后遇到这种问题,去看一下这个变量的内存,你就知道咋回事了
    ufjfeng
        35
    ufjfeng  
       2018-06-15 01:35:19 +08:00
    用 numpy.isclose() 或者自己写一个 isclose() 吧

    https://docs.scipy.org/doc/numpy-1.14.0/reference/generated/numpy.isclose.html
    techmale
        36
    techmale  
       2018-06-15 07:41:56 +08:00 via Android
    RTFM
    Rationalman
        37
    Rationalman  
       2018-06-15 08:17:58 +08:00 via Android
    这两天在看 python 核心编程看到了,是浮点数在计算机中的存储无法精确的问题,了解一下 decimal。我是初学者。
    guog
        38
    guog  
       2018-06-15 08:25:29 +08:00 via Android
    浮点运算请使用 decimal
    littleshy
        39
    littleshy  
       2018-06-15 08:38:25 +08:00   1
    现在学编程都不用学计算机基础?
    xiaojunjor
        40
    xiaojunjor  
       2018-06-15 08:51:39 +08:00
    月经贴
    基础差,不会百度
    没救
    xiaojunjor
        41
    xiaojunjor  
       2018-06-15 08:55:23 +08:00
    yokon
        42
    yokon  
       2018-06-15 09:18:29 +08:00
    戾气都这么重的吗 QAQ~
    broadliyn
        43
    broadliyn  
       2018-06-15 09:25:12 +08:00
    @Leigg 有知识缺口就去补缺口。
    实际上我是不支持有问题就去搜索问题的,

    虽然这样解决问题成本低,但是这些碎片化的知识对你的知识体系的构建来说危害是非常大的。

    你百度出了结果,知道了浮点表示位数是有限的,但是浮点数为什么有限、浮点数二进制是怎么表示的、浮点数二进制四则运算是怎么进行的你缺完全不知道。只知其然,而不知其所以然。
    jmc891205
        44
    jmc891205  
       2018-06-15 13:52:00 +08:00
    @andylsr 不用浮点数是不可能的
    qgb
        45
    qgb  
       2020-10-30 14:12:42 +08:00
    @ufjfeng 与内置 math.isclose 函数不同,上述方程式在 a 和 b 中不对称假定 b 是参考值因此 isclose ( a,b )可能与 isclose ( b,a )不同。此外,atol 的默认值不为零,用于确定应将哪些较小的值视为接近零。默认值适用于阶数为 1 的期望值:如果期望值明显小于 1,则可能导致误报。 应该仔细选择 atol 作为手边的用例。如果 a 或 b 为 atol 的零值将导致 False 是零。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2511 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 32ms UTC 11:13 PVG 19:13 LAX 04:13 JFK 07:13
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86