php中浮点数运算常见问题

本文实例分析了php中让人头疼的浮点数运算。分享给大家供大家参考,具体如下:
在做电商的时候,计算价格是免不了的,然后发现了php的一个坑,口算应该正确的值,php运算出来会跟你不一样
请看下面的代码:

$price=69.1;
$count=100;
$total=$price*$count-6910;
echo $total;

你猜一下变量$total的值是多少,运行一下这个代码输出:-9.09494701773E-13
怎么解决这个问题呢?
使用round函数

代码修改成:

$price=69.1;
$count=100;
$total=round($price*$count)-6910;
echo $total;

浮点数计算结果比较
 一则浮点数计算例子如下:
 
 $a = 0.2+0.7;
 $b = 0.9;
 var_dump($a == $b);
 

打印出的结果是:bool(false)。也就是说在这里 0.2+0.7 的计算结果与 0.9 并不相等,这显然是有违我们的常识的。
 
对此问题,PHP官方手册曾又说明:显然简单的十进制分数如 0.2 不能在不丢失一点点精度的情况下转换为内部二进制的格式。这和一个事实有关,那就是不可能精确的用有限位数表达某些十进制分数。例如,十进制的 1/3 变成了 0.3333333...。
 
我们将上面的变量用双精度格式打印出来:

 $a = 0.2+0.7;
 $b = 0.9;
 printf("%0.20f", $a);
 echo '<br />';
 printf("%0.20f", $b);
 

输出结果如下:
 
 0.89999999999999991118
 0.90000000000000002220
 

显然在这里,实际上作为浮点型数据,其精度已经损失了一部分,达不到完全精确。所以永远不要相信浮点数结果精确到了最后一位,也永远不要比较两个浮点数是否相等。需要说明的是,这不是PHP的问题,而是计算机内部处理浮点数的问题!在 C、JAVA 等语言中也会遇到同样的问题。
 
所以要比较两个浮点数,需要将其控制在我们需要的精度范围内再行比较,因此使用 bcadd() 函数来对浮点数想加并进行精度转换(为字符串):
 

 var_dump(bcadd(0.2,0.7,1) == 0.9); // 输出:bool(true)

浮点数取整
 
在《PHP 取整函数 ceil 与 floor》一文中,曾有例子:
 

 <?php
 echo ceil(2.1/0.7);    // 输出:4
 ?>
 

经过上面对浮点数计算的探讨,知道这是浮点数计算结果不完全精确造成的:
 

 <?php
 printf("%0.20f", (2.1/0.7));    // 输出:3.00000000000000044409
 ?>
 
经过上面对浮点数计算的探讨,知道这是浮点数计算结果不完全精确造成的,因此使用 round() 函数处理一下即可:
 
 <?php
 echo ceil( round((2.1/0.7),1) );
 ?>
 

虽然 round() 函数是按照指定的精度进行四舍五入,但保留小数点后一位,对我们的取整结果是没影响的

时间: 2024-11-01 01:14:24

php中浮点数运算常见问题的相关文章

php中让人头疼的浮点数运算分析_php技巧

本文实例分析了php中让人头疼的浮点数运算.分享给大家供大家参考,具体如下: 在做电商的时候,计算价格是免不了的,然后发现了php的一个坑,口算应该正确的值,php运算出来会跟你不一样 请看下面的代码: $price=69.1; $count=100; $total=$price*$count-6910; echo $total; 你猜一下变量$total的值是多少,运行一下这个代码输出:-9.09494701773E-13 怎么解决这个问题呢? 使用round函数 代码修改成: $price=

DSP中浮点转定点运算--定点数模拟浮点数运算及常见的策略_C 语言

4.定点数模拟浮点数运算及常见的策略 相信大家到现在已经大致明白了浮点数转换成定点数运算的概貌.其实,原理讲起来很简单,真正应用到实际的项目中,可能会遇到各种各样的问题.具我的经验,常见的策略有如下几条: 1)除法转换为乘法或移位运算 我们知道,不管硬件平台如果变换,除法运算所需要的时钟周期都远远多于乘法运算和加减移位运算,尤其是在嵌入式应用中,"效率"显得尤为重要.以笔者的经验,其实,项目中的很大一部分除法运算是可以转换成乘法和移位运算,效率还是有很大提升空间的. 2)查表计算 有些

js中浮点型运算BUG的解决方法说明

 本篇文章主要是对js中浮点型运算BUG的解决方法进行了介绍,需要的朋友可以过来参考下,希望对大家有所帮助 曾经项目用到过的,之前在网上找到此代码,但在特定条件下除法和加法运算依然会出现BUG个人对此稍作优化     代码如下: //除法函数,用来得到精确的除法结果 //说明:javascript的除法结果会有误差,在两个浮点数相除的时候会比较明显.这个函数返回较为精确的除法结果. //调用:accDiv(arg1,arg2) //返回值:arg1除以arg2的精确结果 function acc

java中浮点数的比较(double, float)(转)

  问题的提出:如果我们编译运行下面这个程序会看到什么? public static void main(String args[]){ System.out.println(0.05+0.01); System.out.println(1.0-0.42); System.out.println(4.015*100); System.out.println("BigDecimal:"+new BigDecimal(Double.toString(4.015)).multiply(new

计算机-浮点数运算的问题 (3.14+le20)-le20=0.00?

问题描述 浮点数运算的问题 (3.14+le20)-le20=0.00? 昨天老师上课<程序设计与计算机系统>中说道:(3.14+le20)-le20=0.00,而le20-le20+3.14=3.14, 对前答案的解释是:浮点数在运算时,会有一个对齐问题,这样在非常大的数和3.14相加时,会舍掉有效位,然后只剩le20了,听得不懂而且也没查到资料,所以到这里来求大神来了!先谢了! 解决方案 是的,浮点数有特殊的存储方式,你可以看一下关于浮点数的存储资料,或许能明白一些,维基中有

js中位运算的运用

原文:js中位运算的运用 我们可能很少在编程中用位运算,如果没深入学习,可能也很难理解.平时的数值运算,其实是要先转换成二进制再进行运算的,而位运算就是直接进行二进制运算,所以位运算的执行效率肯定是更高的.下面通过一些实例来加深对位运算的理解. 按位与(&) &&运算符我们都知道,只有两个都为真,结果才为真.&道理是一样的,只有两个数的值为1时,才返回1.例如1和3的按位与操作: 0001 & 0011 --------- 0001 只有对应的数为1时,结果才为1,

Java中浮点数精度问题的解决方法_java

问题描述 在项目中用Java做浮点数计算时,发现对于4.015*100这样的计算,结果不是预料中的401.5,而是401.49999999999994.如此长的位数,对于显示来说很不友好. 问题原因:浮点数表示 查阅相关资料,发现原因是:计算机中的浮点数并不能完全精确表示.例如,对于一个double型的38414.4来说,计算机是这样存储它的: 转成二进制:1001011000001110.0110011001100110011001100110011001100 转成科 学计数法:1.0010

Java简单类型进行精确浮点数运算

运算 由于Java的简单类型不能够精确的对浮点数进行运算,这个工具类提供精确的浮点数运算,包括加减乘除和四舍五入. 以下为代码: import java.math.BigDecimal; public class Arith { //默认除法运算精度 private static final int DEF_DIV_SCALE = 10; //这个类不能实例化 private Arith(){ } /** * 提供精确的加法运算. * @param v1 被加数 * @param v2 加数 *

从java线程中获得运算结果

如果有任何的意见.批评或表扬:),请给我来信climber_2002@sina.com java的线程是由Thread来实现的,一般我们创建线程进行一个复杂的运算,然后在主线程中对运算结果进行处理,但是Thread的run函数并没有返回值,那么我们运算出结果后,怎么通知其它线程呢,本文讲述了几种返回信息的方法. 一.java线程的创建 要创建线程有两种办法,一是继承Thread类,二是实现Runnable,然后将其传递给一个Thread的构造函数,实例如下(假设我们要在一个线程中计算1到1000