电商或财务系统计算钱精度的问题

在电商或财务系统中,浮点数计算可能导致数据不一致,如0.58*100在PHP和JavaScript中计算结果不准确。这是因为二进制浮点数表示的局限性。为解决此问题,PHP提供了BCMath库进行任意精度计算,或使用round函数配合转换为分再转回元的方式确保计算精度。JavaScript中,可以使用Math.round达到类似效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在财务系统中经常,国内最小是分,比如说一件东西0.58元,如果买一百件那应该是58元吧? 用php表示计算

<?php

var_dump(0.58*100) ;//58
?>

结果正确,但是在看一下,下面的结果,怎么就变成57了呢?

<?php
var_dump(intval(0.58*100));//57
?>

是php的bug吗?

那让我们再看一下,javascript,运行下面的代码,你会发现第一个输出怎么不是0.3?

console.log(0.1 + 0.2);   
console.log(0.1 + 0.2 == 0.3);

因此php 表示这个锅,我不背,搞懂这些就要了解浮点数在计算机中表示的方法.

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

0.58的二进制表示基本上(52位)是: 0010100011110101110000101000111101011100001010001111, 如果只是通过这52位计算的话是  0.58 -> 0.57999999999999996,至于0.58 * 100的具体浮点数乘法, 我们不考虑那么细,我们就模糊的以心算来看… 0.58 * 100 = 57.999999999

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

因此浮点数的计算和比较是有误差的.

在php中如何来解决这个问题呢?可以有两种方法

方法1:PHP 为任意精度数学计算提供了二进制计算器(Binary Calculator),它支持任意大小和精度的数字,以字符串(非浮点数)形式描述

bcadd — 加法
bccomp — 比较
bcdiv — 相除
bcmod — 求余数
bcmul — 乘法
bcpow — 次方

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值