有关 PHP 和 js 浮点运算的坑 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
dawang
V2EX    PHP

有关 PHP 和 js 浮点运算的坑

  •  
  •   dawang 2017-10-11 15:07:40 +08:00 2173 次点击
    这是一个创建于 3004 天前的主题,其中的信息可能已经有所发展或是发生改变。

    Javascript

    0.1 + 0.2 为啥不等于 0.3 ? (正确结果:0.30000000000000004 )

    0.8 * 7 为啥不等于 5.6 ? (正确结果:5.6000000000000005 )

    PHP

    var_dump(intval(0.58 * 100));

    正确结果是 57,而不是 58

    浮点运算惹的祸

    其实这些结果都并非语言的 bug,但和语言的实现原理有关,js 所有数字统一为 Number, 包括整形实际上全都是双精度( double )型。

    而 PHP 会区分 int 还是 float。不管什么语言,只要涉及浮点运算,都是存在类似的问题,使用时一定要注意。

    浮点二进制原理

    根据国际标准 IEEE 754,任意一个二进制浮点数 V 可以表示成下面的形式:

    V = (-1)s * M * E 1. (-1)s 表示符号位,当 s=0,V 为正数;当 s=1,V 为负数。 2. M 表示有效数字,大于等于 1,小于 2。 3. 2E 表示指数位。 

    举例来说:十进制的-5.0,写成二进制是-101.0,相当于-1.01×22。那么,s=1,M=1.01 ,E=2。 IEEE 754 规定,对于 32 位的浮点数,最高的 1 位是符号位 s,接着的 8 位是指数 E,剩下的 23 位为有效数字 M。

    对于 64 位的浮点数,最高的 1 位是符号位 S,接着的 11 位是指数 E,剩下的 52 位为有效数字 M。

    IEEE 754 对有效数字 M 和指数 E,还有一些特别规定。

    前面说过,1≤M<2,也就是说,M 可以写成 1.xxxxxx 的形式,其中 xxxxxx 表示小数部分。IEEE 754 规定,在计算机 内部保存 M 时,默认这个数的第一位总是 1,因此可以被舍去,只保存后面的 xxxxxx 部分。比如保存 1.01 的时候,只 保存 01,等到读取的时候,再把第一位的 1 加上去。这样做的目的,是节省 1 位有效数字。以 32 位浮点数为例,留给 M 只有 23 位,将第一位的 1 舍去以后,等于可以保存 24 位有效数字。

    至于指数 E,情况就比较复杂。

    首先,E 为一个无符号整数( unsigned int )。这意味着,如果 E 为 8 位,它的取值范围为 0~255 ;如果 E 为 11 位,它 的取值范围为 0~2047。但是,我们知道,科学计数法中的 E 是可以出现负数的,所以 IEEE 754 规定,E 的真实值必须 由 E 再减去一个中间数,对于 8 位的 E,这个中间数是 127 ;对于 11 位的 E,这个中间数是 1023。 比如,210 的 E 是 10,所以保存成 32 位浮点数时,必须保存成 10(E 的真实值)+127=137(E),即 10001001。

    然后,指数 E 还可以再分成三种情况: ( 1 ) E 不全为 0 或不全为 1。这时,浮点数就采用上面的规则表示,即指数 E 的计算值减去 127 (或 1023 ),得到真实 值,再将有效数字 M 前加上第一位的 1。 ( 2 ) E 全为 0。这时,浮点数的指数 E 等于 1-127 (或者 1-1023 ),有效数字 M 不再加上第一位的 1,而是还原为 0.xxxxxx 的小数。这样做是为了表示±0,以及接近于 0 的很小的数字。 ( 3 ) E 全为 1。这时,如果有效数字 M 全为 0,表示±无穷大(正负取决于符号位 s );如果有效数字 M 不全为 0,表示 这个数不是一个数( NaN )。>

    参考

    http://www.laruence.com/2013/03/26/2884.html
    http://www.cnblogs.com/qlwy/archive/2012/08/17/2644470.html

    原文: http://www.yinqisen.cn/blog-782.html

    azh7138m
        1
    azh7138m  
       2017-10-11 15:34:53 +08:00 via Android
    浮点数就是这样啊,C/C++同样
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2237 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 15:51 PVG 23:51 LAX 07:51 JFK 10:51
    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