上图实际开发业务中,碰到了个坑,
数据库用的 mysql 左边 5.590 在数据库中存储是 decimal(10,3) 右边是换算出来的 float
现在 floatval(5.590) < floatval(5.59)
我 sun
1
elgae 2017-07-26 16:56:51 +08:00
关系到钱的业务用浮点数,心很大。
|
2
7654 2017-07-26 17:00:41 +08:00 3
有个故事,某企财务将全厂工资的几分零头抹掉,每月可偷几千块
|
3
Jacklee 2017-07-26 17:03:50 +08:00 1
计算机存储浮点型都不是精确的,如楼上所说,不能直接比较大小啊。涉及钱的业务更不能用啊。
|
4
Jacklee 2017-07-26 17:04:25 +08:00
补一句,这不是 PHP 的锅哈
|
5
oh 2017-07-26 17:09:27 +08:00 1
抛去楼上已解决说的,不知道楼主有没有试过在 if 前面 var_dump(floatval()) 看看这两个变量对比的时候是多少?
|
6
Biscuits 2017-07-26 17:12:44 +08:00 2
5.59 可能是 5.5904444
|
7
bombless 2017-07-26 17:12:46 +08:00 1
比较的时候乘 100 按整数比吧
|
8
lujiajing1126 2017-07-26 17:12:52 +08:00 via iPhone
楼主需要复习一下 IEEE754
|
9
goodspb 2017-07-26 17:12:56 +08:00
php > var_dump(floatval(5.590) < floatval(5.59));
php shell code:1: bool(false) php > var_dump(floatval(5.590) == floatval(5.59)); php shell code:1: bool(true) php > var_dump(5.590 == 5.59); php shell code:1: bool(true) php > var_dump(5.590 < 5.59); php shell code:1: bool(false) 恩?有啥问题? php -v 一下 PHP 5.6.30 (cli) (built: Apr 17 2017 10:09:18) Copyright (c) 1997-2016 The PHP Group Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2016, by Zend Technologies with Xdebug v2.5.3, Copyright (c) 2002-2017, by Derick Rethans |
10
ovear 2017-07-26 17:14:02 +08:00 1
请使用 bccomp
|
11
exch4nge 2017-07-26 17:14:53 +08:00
对 PHP 不熟悉……不过表示金钱的类型应该用专门的 decimal 类型吧……
|
13
gclove 2017-07-26 17:15:50 +08:00
同上, 计算千万不要用符点, 还不如用大数计算
建议直接乘 100 取整 为什么设置 3 位, 你们应用还有微分 ? 有的话可以乘以 1000 取整 浮点在每种变成语言都有陷阱(坑), 经验不够老练都会踩上 |
14
gclove 2017-07-26 17:21:30 +08:00
非用浮点, 计算前值一定要进行类型转换
因为你不知道它是 整数, 浮点, 还是 字符串 |
15
solaro OP 本地开发环境用 5.6.27 没毛病,生产环境用 7.1 就触发异常。。。我日
|
16
doushiyinweini 2017-07-26 17:24:10 +08:00 1
|
17
moult 2017-07-26 17:25:36 +08:00
就算知道什么情况下出现这个问题,那又如何?
1、从数据库里面查询出来的浮点数,请使用 string。 2、http://php.net/manual/en/book.bc.php 3、个人癖好,有段时间,金钱我用 int 来存储,单位是分。不过现在都用 string 来做了。 |
20
zhs227 2017-07-26 17:34:48 +08:00
涉及到价格我每次都是*100 以后按整数存。float 的比较容易出问题,越相近越容易出问题。
|
22
ety001 2017-07-26 17:54:37 +08:00
之前用过整数(就是存储到分),后来就用 decimal 了。
|
23
oneonesv 2017-07-26 18:00:31 +08:00
浮点数精度不够 可能会有类似 0.111 != 0.111 的情况
PHP 文档 浮点数 章节里面有讲 |
24
stabc 2017-07-26 18:01:02 +08:00
谁能说下这种浮点数在计算中常见的坑?
|
25
LioMore 2017-07-26 18:06:16 +08:00
请问一下,正确的做法是只用分来计算并使用整数吗?
|
27
maypu 2017-07-26 18:49:14 +08:00 via Android
算错的时候,哈哈哈哈哈哈
|
28
a591826944 2017-07-26 19:54:37 +08:00
LZ 你的心真大。。浮点数算金额。。
|
29
a591826944 2017-07-26 19:55:11 +08:00 1
LZ 你试试 floor(8.29 * 100 * 100 / 100) 的结果 体会一下。。。
这真不是 PHP 的锅、、 |
30
bianchensz 2017-07-26 21:11:56 +08:00 1
233 就算是我老妈用 excel 涉及到钱的都要套个 round 取整,你这也是心大
|
31
xzem 2017-07-26 22:10:14 +08:00 via Android
被浮点坑过一次,再也不敢用浮点做计算 比较了
|
32
blankme 2017-07-26 22:18:51 +08:00 1
```
if (fabs(a - b) > 1e-3 && a < b) ``` |
33
zhx1991 2017-07-26 23:16:42 +08:00 1
钱用浮点数什么都可能发生
想追究细节的话了解一下计算机怎么表示小数就明白了 |
34
stabc 2017-07-26 23:35:50 +08:00 1
看一下这个明白了:
https://kknews.cc/tech/p8bpz2p.html |
35
incompatible 2017-07-26 23:42:03 +08:00 4
@LioMore 不是,不要听本帖的草台班子们胡扯用什么 int。正确的方法是用 decimal。
PHP 用户可以看一下 http://de2.php.net/manual/en/ref.bc.php |
36
dikT 2017-07-26 23:48:08 +08:00 1
现在想想微信的钱 fee 就是按分来存储.当时觉得很奇怪, 恍然大悟[doge]
|
37
wsy2220 2017-07-26 23:54:47 +08:00
心真大
|
38
msg7086 2017-07-27 00:16:47 +08:00
浮点数大都是不精确的数据存储。
比如 5.59 这个数就无法用浮点数表达,因为在二进制中是个无理数。 |
39
LioMore 2017-07-27 00:20:13 +08:00
@incompatible 好的,感谢
|
40
solaro OP 被坑到了。谢谢各位
|
41
incompatible 2017-07-27 18:09:45 +08:00 via iPhone 1
@solaro int 或 bigint 没法处理小数位数,两个数相除时是要处理结果保留几位小数以及 ceiling(四舍五入 / 去尾 / 进一)的规则的,所以应该用(数学意义上的)decimal。
那哥们用 string 的原因是 php 这个所谓的最好的语言居然没有内置对 decimal 的支持,而是需要通过 bc extension 处理 string 来实现对 decimal 的操作。 |
42
lestat 2017-07-28 20:14:58 +08:00 via iPhone
写个专门运算的函数,全部乘以 100 之后运算,把结果再除以 100 返回,可以参考微信支付的做法
|