var a = 0.05
a += 0.01
这时候 a 会等于 0.060000000000000000000005
1
luban 2016-08-01 18:10:55 +08:00 1
二进制保存小数问题,基本上编程语言都有类似的问题
|
2
lovedebug 2016-08-01 18:10:57 +08:00 1
JS 是双精度浮点数,用的 IEEE754 ,因而浮点数数值计算本来就不可能精确
|
3
zoudm 2016-08-01 18:17:24 +08:00 via iPhone
因为浮点数是实数的近似表示。计算的时候就会产生误差。跟具体什么语言没有关系。
C 里面可以自己决定使用 32 位的 float 或 64 位的 double , python 默认都是 64 位的浮点数。 定义一个 double d = 0.1 ,再 printf("%.20lf", d),就可以知道浮点数是无法准确表示 0.1 的。 |
4
CodingPuppy 2016-08-01 18:18:20 +08:00 via Android
跟语言没关系
|
5
br00k 2016-08-01 18:27:12 +08:00 via iPhone
和语言没关系
|
6
InFaNg 2016-08-01 19:14:44 +08:00 via Android
js 日常背锅
|
7
laoyur 2016-08-01 19:24:20 +08:00
In [1]: a = 0.05
In [2]: b = 0.01 In [3]: a + b Out[3]: 0.060000000000000005 Python 表示这个锅有 js 帮背,真舒坦 |
8
exoticknight 2016-08-01 19:34:03 +08:00
心痛 js
|
9
SourceMan 2016-08-01 19:48:10 +08:00 via iPhone
日常背锅
|
10
aristotll 2016-08-01 19:48:43 +08:00
Js 表示虽然我设计的差 但真不是我的锅啊
|
11
FrankFang128 2016-08-01 19:51:38 +08:00
楼主找 block 么
|
12
billlee 2016-08-01 19:58:39 +08:00
自己计算机基础都没学好,还怪 js
|
13
iVanilla 2016-08-01 20:12:05 +08:00
我用 PHP 无法还原这个过程,不知什么原因。
<?php $a = 0.05; $a += 0.01; echo $a; ?> 输出: 0.06 |
14
YuJianrong 2016-08-01 20:17:45 +08:00
|
15
iVanilla 2016-08-01 20:25:13 +08:00
@YuJianrong 如果数值大一些, PHP 也可以出现类似现象,鸟哥在他的博客有解释: http://www.laruence.com/2013/03/26/2884.html
如果说这帖子是钓鱼的话,只能说钩直饵咸。 |
17
justjavac 2016-08-01 20:29:00 +08:00 via Android
|
18
zhanglintc 2016-08-01 20:34:15 +08:00 2
不知道你有没有听说过一个网站:
http://0.30000000000000004.com/ |
20
iVanilla 2016-08-01 20:41:56 +08:00
@zhanglintc 看了你这个链接之后用 PHP 复现成功。
<?php ini_set('precision', 17); $a = 0.05; $a += 0.01; echo $a; ?> 官方的解释: http://php.net/manual/zh/ini.core.php#ini.precision 浮点数中显示有效数字的位数。 我看了下, PHP7 的默认值是 14. |
21
zhanglintc 2016-08-01 20:52:57 +08:00
@iVanilla PHP 不是很熟哦. 不过你一说我突然想起来, 当时 PHP 这段我把我看笑了. PHP 居然如此机智的避开了这个问题.
|
22
russj 2016-08-01 20:55:30 +08:00
心疼 js
|
24
ljcarsenal 2016-08-01 21:09:29 +08:00 via Android
不如认真读一下 csapp
|
25
y 2016-08-01 21:15:28 +08:00 6
0.01 和 0.05 都是二进制下的无限循环小数,没法用 64 bit 表示
所以只能作为双精度浮点数存在 0.01 表示为 0x3f847ae147ae147b, 也就是二进制的 1.0100011110101110000101000111101011100001010001111011 * 2^-7 0.05 表示为 0x3fa999999999999a, 也就是二进制的 1.1001100110011001100110011001100110011001100110011010 * 2^-5 用竖式加起来 1.111010111000010100011110101110000101000111101011100011 * 2^-5 注意这个结果已经比原来的小数长了两位(末尾的 11 ),现在要做四舍五入 0.06 是 1.1110101110000101000111101011100001010001111010111000 * 2^-5 而 0.060000000000000005 是 1.1110101110000101000111101011100001010001111010111001 * 2^-5 显然后者的误差更小。 最后吐槽一下楼主的态度: 实际答案明明是 0.060000000000000005 , 楼主原帖多了六个 0 ,复制粘贴都不会吗,一定要手打? (我一定是知乎玩多了...) |
26
kideny 2016-08-01 21:20:43 +08:00
楼主这被打脸的不清啊。
|
27
iVanilla 2016-08-01 21:37:38 +08:00
@zhanglintc 我开始以为之前很多人在 bugs.php.ne 反馈了,然后官方把这个值改了,不过我去 https://secure.php.net/releases/ 下载了十多年前的 PHP4.3.11 和 PHP5.0.0 ,发现这个值都是 14 。
@11138 很奇怪为什么你那个例子在不改 precision 的情况下能复现。 |
28
hasbug 2016-08-01 21:38:46 +08:00
IEEE 754···
|
29
11138 2016-08-01 21:56:23 +08:00
@iVanilla 设置 precision 影响显示的值的位数(整数部分和小数点部分),但是开始和结尾部分的 0 不算数。
<?php $num = 0.012345600000000000; ini_set("precision", "12"); echo $num; // 0.0123456 echo "\n"; ini_set("precision", "3"); echo $num; // 0.0123 echo "\n"; ini_set("precision", "5"); echo $num; // 0.012346 echo "\n"; ?> |
30
y 2016-08-01 21:58:49 +08:00 1
@iVanilla 顺便说一句,如果有人要开发一套类似于支付宝的系统(或者 V2EX 的货币系统),那货币的金额一定要是 “ 1 分钱” 的整数倍,而不是有 “ 0.01 元” 这样的数据。所有的数据都要用整型表示,显示的时候再加上小数点,否则时间长了算账的时候会疯掉的。
举个例子,消失的一元钱: >>> 9999999999999999.0 + 1 - 9999999999999999 0.0 |
31
maomaomao001 2016-08-01 22:16:29 +08:00 via Android
@kideny 什么叫被大脸????
他不是在好好的问问题吗???? |
32
br00k 2016-08-01 22:19:07 +08:00
|
35
gilgamesh 2016-08-01 22:44:09 +08:00
|
36
ychongsaytc 2016-08-01 23:12:44 +08:00 1
「你看似有穷的小数, 在计算机的二进制表示里却是无穷的」
---from http://www.laruence.com/2013/03/26/2884.html |
37
kzzhr 2016-08-01 23:27:27 +08:00 via Android
相当一部分语言算不好 0.1+0.2-0.3 我记得
|
38
jeffersonpig 2016-08-02 08:51:00 +08:00
LZ 大一?
|
39
FrankHB 2016-08-02 10:03:49 +08:00
@lovedebug 你数一下 0 的个数大概就不能指望是 IEEE-754 的双精度了,起码是扩展双精度。
@iVanilla PHP 还真有相关的 bug ,而且曾经造成了比较严重的后果,不过具体表现和系统相关: https://bugs.php.net/53632 |
41
onceyoung 2016-08-02 11:54:56 +08:00 via iPhone
这个跟语言什么关系?
|
42
winglight2016 2016-08-02 11:58:06 +08:00
@y 我做的微信商城的确是这样设计的
|
44
intsilence 2016-08-02 15:54:20 +08:00
JavaScript : 怪我咯?
|
45
miss61008596 2016-08-16 17:38:57 +08:00
c#的 decimal 和 Java 的 BigDecimal 之所以没有出现精度差异,只是因为在其内部作了相应处理,把这种精度差异给屏蔽掉了,
javascript decimal.js big.js http://mikemcl.github.io/decimal.js/ http://mikemcl.github.io/big.js/ -勤于思,敏于行。 |