php 浮点数问题,PHP浮点数用法与问题总结

在PHP浮点数处理函数在PHP中有很多,包括有如ceil,floor,round,intval 经过他们处理之后可返回我们想要的浮点数小数位了,下面我来介绍一些关于PHP浮点数用法与问题分析。

一,PHP浮点数用法

PHP浮点类型取整之ceil — 进一法取整

说明:float ceil (float value)

返回不小于 value 的下一个整数,value 如果有小数部分则进一位。ceil() 返回的类型仍然是 float,因为 float 值的范围通常比 integer 要大。

例子1. ceil() 例子,实例代码如下:

echoceil(4.3);// 5

echoceil(9.999);// 10

?>

PHP浮点类型取整之floor — 舍去法取整

说明:float floor (float value)

返回不大于 value 的下一个整数,将 value 的小数部分舍去取整。floor() 返回的类型仍然是 float,因为 float 值的范围通常比 integer 要大。

例子1. floor() 例子,代码如下:

echofloor(4.3);// 4

echofloor(9.999);// 9

?>

PHP浮点类型取整之round — 对浮点数进行四舍五入

说明:float round ( float val [,int precision] )

返回将 val 根据指定精度 precision(十进制小数点后数字的数目)进行四舍五入的结果。precision 也可以是负数或零(默认值)。

例子1. round() 例子,代码如下:

echoround(3.4);// 3

echoround(3.5);// 4

echoround(3.6);// 4

echoround(3.6, 0);// 4

echoround(1.95583, 2);// 1.96

echoround(1241757, -3);// 1242000

echoround(5.045, 2);// 5.05

echoround(5.055, 2);// 5.06

?>

PHP浮点类型取整之intval—对变数转成整数型态

例子intval(),代码如下:

echointval(4.3);//4

echointval(4.6);// 4

?>

二,浮点数转成字符串

PHP内置的echo,var_dump,json_encode,字符串拼接等函数(指令)在显示浮点数时都有问题,导致精度丢失.实例代码如下:

$a= 1315537636.338467;

printf("%f",$a);echo"n";

echo$a."n";

echo$a;echo"n";

?>

/*

结果

1315537636.338467

1315537636.3385

1315537636.3385

*/

也就是说,用PHP最顺手的方法将浮点数转成字符串或者显示是不行的,必须使用printf/sprintf将浮点数转成字符串.

三,一个常见问题的解答

不过,我当时遗漏了一点,也就是对于如下的这个常见问题的回答,实例代码如下:

$f= 0.58;

var_dump(intval($f* 100));

?>

为啥输出57

为啥输出是57啊? PHP的bug么?我相信有很多的同学有过这样的疑问,因为光问我类似问题的人就很多,更不用说bugs.PHP.net上经常有人问…

要搞明白这个原因,首先我们要知道浮点数的表示(IEEE 754):

浮点数,以64位的长度(双精度)为例,会采用1位符号位(E),11指数位(Q),52位尾数(M)表示(一共64位).

符号位:最高位表示数据的正负,0表示正数,1表示负数。

指数位:表示数据以2为底的幂,指数采用偏移码表示

尾数:表示数据小数点后的有效数字.

这里的关键点就在于,小数在二进制的表示,关于小数如何用二进制表示,大家可以百度一下,我这里就不再赘述,我们关键的要了解,0.58 对于二进制表示来说,是无限长的值(下面的数字省掉了隐含的1)..

0.58的二进制表示基本上(52位)是:

0010100011110101110000101000111101011100001010001111

0.57的二进制表示基本上(52位)是:

0010001111010111000010100011110101110000101000111101

而两者的二进制,如果只是通过这52位计算的话,分别是:

0.58 -> 0.57999999999999996

0.57 -> 0.56999999999999995

至于0.58 * 100的具体浮点数乘法,我们不考虑那么细,有兴趣的可以看(Floating point),我们就模糊的以心算来看… 0.58 * 100 = 57.999999999

那你intval一下,自然就是57了….

可见,这个问题的关键点就是:“你看似有穷的小数,在计算机的二进制表示里却是无穷的”

四,float(浮点数)比较的问题

最近在开发一个合同管理系统的时候,涉及到两个浮点数比较,算是把我郁闷惨了。

在N久以前,就不晓得从哪里听来的一个“不要用等号去比较浮点数”的“真理”,自己平时也在用,好像没有出现啥问题,可这次问题总算是来了,实例代码如下:

$sum="12300.00";

$a="10000.30";

$b="2000.30";

$c="299.40";

$sum= (float)$sum;

$s= (float) ($a+$b+$c);

var_dump($sum,$s);

var_dump($sum==$s);

/*

结果是:

float(12300)

float(12300)

bool(false)

*/

后来才知道在PHP中,要比较两个浮点数的大小,可以用bccomp(参数1,参数2,小数位)来比较, $s);

var_dump(bccomp($sum,$s,2));

/*

结果:

float(12300)

float(12300)

int(0) // 0表示两个浮点数值相等

*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值