Leigg
V2EX  ›  Python

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

By Leigg at 2018 年 6 月 14 日 · 9937 次点击

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

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

@SuperMild 就是不知道咋搜啊
crayygy
   5
crayygy  
   2018 年 6 月 14 日 via iPhone
IEEE754
Leigg
   6
Leigg  
OP
   2018 年 6 月 14 日
@broadliyn 老哥担待一下,我也不是大佬,啥都懂,总有知识缺口。
rabbbit
   7
rabbbit  
   2018 年 6 月 14 日
kingname
   8
kingname  
   2018 年 6 月 14 日   ❤️ 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 年 6 月 14 日 via Android
离散数学了解下?
cuzfinal
   10
cuzfinal  
   2018 年 6 月 14 日   ❤️ 12
zynlp
   11
zynlp  
   2018 年 6 月 14 日 via iPhone
加个 round
araraloren
   12
araraloren  
   2018 年 6 月 14 日
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 年 6 月 14 日
永远不要用==去比较浮点数
suilin
   14
suilin  
   2018 年 6 月 14 日
几位大佬包容下嘛(手动狗头
robinlovemaggie
   15
robinlovemaggie  
   2018 年 6 月 14 日
打个比方:你把一个蛋糕切成三块再拼到一起,它还是一个蛋糕吗?
SingeeKing
   16
SingeeKing  
   2018 年 6 月 14 日
涉及浮点数判断请使用 round

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

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

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

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

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

你百度出了结果,知道了浮点表示位数是有限的,但是浮点数为什么有限、浮点数二进制是怎么表示的、浮点数二进制四则运算是怎么进行的你缺完全不知道。只知其然,而不知其所以然。
jmc891205
   44
jmc891205  
   2018 年 6 月 15 日
@andylsr 不用浮点数是不可能的
qgb
   45
qgb  
   2020 年 10 月 30 日
@ufjfeng 与内置 math.isclose 函数不同,上述方程式在 a 和 b 中不对称–假定 b 是参考值–因此 isclose ( a,b )可能与 isclose ( b,a )不同。此外,atol 的默认值不为零,用于确定应将哪些较小的值视为接近零。默认值适用于阶数为 1 的期望值:如果期望值明显小于 1,则可能导致误报。 应该仔细选择 atol 作为手边的用例。如果 a 或 b 为 atol 的零值将导致 False 是零。
推荐学习书目
› 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
© 2026 V2EX · 103ms · 3.9.8.5