鱼C论坛

 找回密码
 立即注册
查看: 2582|回复: 0

[技术交流] 【php包教不包会系列9】PHP 类型之浮点型

[复制链接]
发表于 2017-3-8 00:28:27 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 mumudontcry 于 2017-3-8 00:38 编辑

浮点型

浮点型(也叫浮点数 float,双精度数 double 或实数 real)
  1. <?php

  2. $a = 1.234;
  3. $b = 1.2e3;
  4. $c = 7E-10;
复制代码


浮点数的精度

浮点数的精度有限。尽管取决于系统,PHP 通常使用 IEEE 754 双精度格式,则由于取整而导致的最大相对误差为 1.11e-16。非基本数学运算可能会给出更大误差,并且要考虑到进行复合运算时的误差传递

这是手册上的解释,更多的解释其实归结起来就是,浮点数的精度不可信!如果你要精确的浮点数精度,那么还是请使用bc math库,是内置的,在手册的数学扩展中你可以方便找到它:http://php.net/manual/zh/ref.bc.php

转换为浮点数

它的规则是,先把数值转成整型,然后再转成浮点型

比较浮点数

刚才说了,浮点数的精度是不靠谱的!所以,如果要比较两个浮点数大小怎么办?用“==”?或者是“===”?都不是

由于机器的内部问题,浮点数比较大小应该用一个更加科学的方式,而不是直接比较:

我们用数学的思维去处理这个问题,在概率学里,有一个关于不可能事件的描述:发生概率小于0.05%的事件被称为“不可能事件”(ps:我忘了这个概率具体是多少,但是我记得高中课本是这么个类似的描述的)

当两个数的差小于可以接受的程度的时候,我们可以认为这两个数其实是相等的,这个误差我们叫做,机器极小值(epsilon)或最小单元取整数

如果误差小于小数点后五位,那么认为两个数是相等的
  1. <?php
  2. $a = 1.23456789;
  3. $b = 1.23456780;
  4. $epsilon = 0.00001;

  5. if(abs($a-$b) < $epsilon) {
  6.     echo "true";
  7. }
复制代码


NaN

某些数学运算会产生一个由常量 NAN 所代表的结果。此结果代表着一个在浮点数运算中未定义或不可表述的值。任何拿此值与其它任何值进行的松散或严格比较的结果都是 FALSE。

由于 NAN 代表着任何不同值,不应拿 NAN 去和其它值进行比较,包括其自身,应该用 is_nan() 来检查

NaN其实就是“not a number”的简写,比如,我们知道,反余弦的定义域是-1到1,那么下面的例子,你会得到一个NaN
  1. <?php

  2. $nan = acos(8);

  3. var_dump($nan, is_nan($nan));
复制代码


一些重要的话

1、浮点数确实是不靠谱的,在作业部分我会给两个例子,两个看了让女生脸红,让男生。。。额(我想多了么?),让人郁闷的例子,来说明浮点数的不靠谱,简单说,如果你非要精确度高,那么就用bc math库的函数去计算浮点数

2、和整型一样,一些强制转换也会得到奇怪的结果,因此,不要试图理所当然转换,或者。。。比较

3、尽管如此,在 web 应用上,你可能并不会接触到那么多这样的问题(如果有,请用bc math。。。),所以,也不用太紧张

作业

1、运行下面的代码,嗯。你运行了就知道为什么奇怪了,结论是,在浮点数计算中,不要把浮点数强制转换成整型,否则后果自负
  1. <?php

  2. echo intval(19.31 * 100);
复制代码


2、参看:http://baike.baidu.com/link?url=X9f_7MR37pjIgclcXIkwzb52uENPYV0VYOXOar9Gis4o1mwY5a0LoWlKFsrGwdxPORwee_aaMn1QIcbT8Vc3VzhLkZxQHOPSGHCkarTu3z1E6YtUwzm14EKRqGK__LwjlDpbHW9a_TXNbZ7sP72dAK

斐波那契数列是老生常谈的问题,其实斐波那契数列有一个通项公式!在数学上你并不需要像程序递归啊,循环那样去计算第n项的值,而因为浮点数精度的问题,你才需要用程序的方式去计算(因此你以往做的斐波那契程序题都不会有这个公式!),其实就是说白了用无理数计算有理数(纳尼?)

完成下面的公式的代码,然后自己计算某些项的值,看看浮点数在其中起到的作用。。。顺便提一句,你就算用bc math 也没有用,毕竟公式里的是无理数,计算机是无法精确表示这样的浮点数的!提示,根号的函数是:sqrt,a的n次方可以用pow(a, n)得到,而在 php 5.6 (包括 5.6)之后,你可以像 python 那样去表示一个幂运算:a ** n
503d269759ee3d6db9e6f1e046166d224f4adefd.jpg


其他:女生节快乐~哦,已经过了零点,女王节快乐,prpr


#################### 华丽的 PHP 版分割线 ####################


如果喜欢木木的讲解,就点击下方的订阅(读作:打赏),给木木点个赞吧,欢迎大家提出建议或者指正

一块钱买不了皮肤,买不了香烟,却可以跟着木木一起打怪升级,并给木木巨大的支持,有了大家的力量,木木就可以制造元气弹,打败……嗯,买一个好一点的女朋友啦

评分

参与人数 1荣誉 +20 鱼币 +20 贡献 +10 收起 理由
hldh214 + 20 + 20 + 10 热爱鱼C^_^

查看全部评分

本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-16 13:20

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表