金融系统为什么只保留两位小数,如果产生多余两位小数位的金额怎么办?
突然发现个问题,我们生活中的金融系统最多只有两位小数位,比如12.37,精确到分,但是当两位小数和非整数计算时也会得出三位小数啊,比如银行的日率,肯定会有计算得出三位小数或者更多小数位的,但是为什么我们只看得到两位小数的余额呢,多出的小数位不也是钱吗,被省略了吗,怎么省略的呢。感觉这个问题有点意思。
我的猜想:
实际上只要我们金融系统只是用两位小数,当产生超过两位小数时,后面的小数位都不要了,直接不要,而不是满五进一,如果进一,就造成多给用户钱了,哪怕是多给0.001元,这在整个系统中的损失也是巨大的,所以当出现两位以上的小数时,只能直接省去后面的小数位,哪怕是0.239也要省去0.009,这个0.009元的损失只能让用户承担。
比如银行的系统,支付宝,这些都是两位小数位的,我们一般余额字段都是使用decimal(10,2)
,保留两位小数位,我突然想到这个问题,好纠结,不知道是不是我想的那样。
比如支付宝使用积分,购物券抵扣同时下多个订单时,那个抵扣的钱好像就是根据订单金额的比例拆分到每个订单下面去了,这样就出现小数了,但是那个小数也是两位,我没仔细注意过,不知道多个订单的抵扣加起来是不是等于下单时抵扣的钱。
如果是我想的那样,那这样我感觉很多时候我们肯定损失了好多钱了?我原本想多保留几位小数就可以解决这个问题,可是感觉可能还会有无穷的小数,还是不太可能,难道就只能让用户损失钱吗,哪怕只是那么一点点。
希望大神指点一下,搞得我好迷惑,目前项目中正遇到了这类问题。
谢谢!
回复内容:
突然发现个问题,我们生活中的金融系统最多只有两位小数位,比如12.37,精确到分,但是当两位小数和非整数计算时也会得出三位小数啊,比如银行的日率,肯定会有计算得出三位小数或者更多小数位的,但是为什么我们只看得到两位小数的余额呢,多出的小数位不也是钱吗,被省略了吗,怎么省略的呢。感觉这个问题有点意思。
我的猜想:
实际上只要我们金融系统只是用两位小数,当产生超过两位小数时,后面的小数位都不要了,直接不要,而不是满五进一,如果进一,就造成多给用户钱了,哪怕是多给0.001元,这在整个系统中的损失也是巨大的,所以当出现两位以上的小数时,只能直接省去后面的小数位,哪怕是0.239也要省去0.009,这个0.009元的损失只能让用户承担。
比如银行的系统,支付宝,这些都是两位小数位的,我们一般余额字段都是使用decimal(10,2)
,保留两位小数位,我突然想到这个问题,好纠结,不知道是不是我想的那样。
比如支付宝使用积分,购物券抵扣同时下多个订单时,那个抵扣的钱好像就是根据订单金额的比例拆分到每个订单下面去了,这样就出现小数了,但是那个小数也是两位,我没仔细注意过,不知道多个订单的抵扣加起来是不是等于下单时抵扣的钱。
如果是我想的那样,那这样我感觉很多时候我们肯定损失了好多钱了?我原本想多保留几位小数就可以解决这个问题,可是感觉可能还会有无穷的小数,还是不太可能,难道就只能让用户损失钱吗,哪怕只是那么一点点。
希望大神指点一下,搞得我好迷惑,目前项目中正遇到了这类问题。
谢谢!
有个 银行家舍入 的方法,即:
舍去位的数值小于5时,直接舍去;
舍去位的数值大于等于6时,进位后舍去;
当舍去位的数值等于5时,分两种情况:5后面还有其他数字(非0),则进位后舍去;若5后面是0(即5是最后一位),则根据5前一位数的奇偶性来判断是否需要进位,奇数进位,偶数舍去。
按上述规则举例,假设我们要求数字要求精确到个位:
<code>49.6101 -> 50 49.499 -> 49 49.50921 -> 50 48.50921 -> 48 48.5101 -> 49</code>
有个很好的例子来看出这种计算方式的优势:
2.55 + 3.45 = 6
如果我们要保留一位小数,去转换 2.55 和 3.45,则会变成这样:
2.6 + 3.5 = 6.1
很显然这样多了 0.1,那么按照我们的 “四舍六入五成双” 再来计算,2.55 实际上可以说是 2.550,我们要舍去的 5 的后面是 0,则根据前面一位的奇偶判断是否进位,很显然前面为奇数,则进位后为 2.6,对于 3.45,5 前面是偶数,则舍去,结果为 3.4,因此两者计算如下:
2.6 + 3.4 = 6
2016-11-24 补充说明
有人提出了 2.55 + 2.55 实际依旧多算了 0.1,而我为什么没有举这个例子呢?因为用 四舍五入,也会存在这个情况。重点是 2.45 + 2.45,常规的四舍五入会被舍去,我们需要避免这种接近中间值却未进位的情况,因为只有这样,才能保证 近似计算中舍去和进位的概率相等
。这才是主要目的。毕竟只要精度有限必定存在损耗,我们只需要保证在大量样本下,概率相等即可。
这块的资金问题还是得考虑业务需求的。按我以前的做法,是保存4位小数。根据不同的场景,进行取舍!但前台所有显示的金额都只显示2位,并向下取数
如以下场景:
余额提现、转出等
一般会向下取数
,比如10.1234
;那实际可提现金额为10.12
。
分期相关
如银行额度总共为1000元,然后刚好买了一样东西,全花了,在操作分期。分3期;
按正常思维是1000/3=333.3333333
;在四舍五入一下就成了333.33
;等你三期都还完了,发现只还了999.99
。这就坑了
一般做法是:
前2期按四舍五入计算。最后一期,按减法算:1000-333.33-333.33=333.34
;
其他说明
根据不同业务,保留位数和取舍都不一样。如基金的净值。小数点的长度影响的资金量还是很大的。这块是越精准越好。具体需求跟产品沟通吧!
其实并不是这样。我们电商财务系统在进行对账和对佣的时候通通算到了后6位。decimal(16, 6)在计算完之后才会四舍五入。一般最后四舍五入这一步是写在 协议里面的,最后一步我觉得应该属于协商的范畴吧。跟系统已经没啥关系了。
不懂很专业的东西,但是我觉得做系统没什么考虑的,两位小数后面的全部用户损失
如果进账0.111记成0.11
如果出账0.111只出0.11
当然不会是两位,在计算和存储都是6位及以上(有没有更多,不太清楚,但最少6位是肯定的)
只是算到最终给用户的 由于分之后无法兑现 所以就按照一定的算法计算最终结果。
计算机中的整数1 跟小数1.0是不相等的,所以在金钱上的小数换算为整数做处理
我觉得比较稳妥的方式的数据库存储的金额字段计量单位使用分,这样前台显示的时候先取整,再除100就是元了.
计算方式得分"给"和"收",以银行为主体的话,
"给":如果字段值是 200.11 那么算成元是2元零1.1厘..这个1.1厘可以舍去了,只给2元即可,就是说只取整数部分.
"收":相对可以自私一点.本着绝对不吃亏的设计原则,1厘也要算1分.那么就是字段值判断是否有小数点,有的话取整+1,没有的话直接取.如果本着四舍五入的话..各位大神就需要对有小数点的值进行判断和处理了.个人偏向绝对不吃亏原则,这个原则也应该是金融机构通用的原则.
重点时,用分做金额的计量单位,如果上亿的话,需要考虑下数据类型的Max,别超出范围了.
题主你居然发了金融机构秘密圈钱的手段,哈哈哈。
收款时直接把分以后的数字进位处理,付款时直接截去分以后的小数位。
展示显示2位小数不代表系统中处理都是2位小数吧。我觉得应该会有很多位
要么四舍五入,要么向下取整,保留两位
合理的均分方法可以固定小数位.
比如100元平均分成N份(保留2为小数)并计算尾差:
<code><?php header('Content-Type: text/plain; charset=utf-8'); function tail($num, $fen) { $avg = bcdiv($num, $fen, 2); //除 $tail = bcsub($num, $avg*($fen-1), 2); //减 echo $num.'='.str_repeat($avg.'+', $fen-1).$tail."\n"; echo "$num=$avg*($fen-1)+$tail\n"; return array($avg, $tail); } var_export(tail(100, 3)); var_export(tail(100, 6)); //输出: 100=33.33+33.33+33.34 100=33.33*(3-1)+33.34 array ( 0 => '33.33', 1 => '33.34', ) 100=16.66+16.66+16.66+16.66+16.66+16.70 100=16.66*(6-1)+16.70 array ( 0 => '16.66', 1 => '16.70', )</code>
4舍5入,没有什么好纠结的,相信老祖宗的智慧。
从统计学的角度上来看,在大规模的应用的情况下,你们金融系统多出来的和少掉的钱是近似的,同样的,用户多出来和少掉的钱也是近似的,没有必要纠结。
没有做过金融系统开发,权当抛砖引玉了。

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

利用地理空间技术高效处理700万条记录并创建交互式地图本文探讨如何使用Laravel和MySQL高效处理超过700万条记录,并将其转换为可交互的地图可视化。初始挑战项目需求:利用MySQL数据库中700万条记录,提取有价值的见解。许多人首先考虑编程语言,却忽略了数据库本身:它能否满足需求?是否需要数据迁移或结构调整?MySQL能否承受如此大的数据负载?初步分析:需要确定关键过滤器和属性。经过分析,发现仅少数属性与解决方案相关。我们验证了过滤器的可行性,并设置了一些限制来优化搜索。地图搜索基于城

DevOps工程师常面临RDS数据库优化与更新的挑战,尤其在高负载情况下,传统方法易导致停机风险。本文介绍AWS蓝/绿部署策略,实现RDS数据库零停机时间更新。告别数据库更新停机噩梦!本文将详细讲解蓝/绿部署策略,并提供AWS环境下的操作步骤,助您在不影响服务可用性的前提下,更新RDS数据库实例。准备工作首先,协调开发团队,选择工作负载流量最低的时段进行更新。良好的DevOps实践建议提前通知团队。本例演示如何利用蓝/绿部署,在零停机时间内缩减数据库实例存储空间。您可以通过AWSRDS控制台

MySQL 可在无需网络连接的情况下运行,进行基本的数据存储和管理。但是,对于与其他系统交互、远程访问或使用高级功能(如复制和集群)的情况,则需要网络连接。此外,安全措施(如防火墙)、性能优化(选择合适的网络连接)和数据备份对于连接到互联网的 MySQL 数据库至关重要。

MySQL启动失败的原因有多种,可以通过检查错误日志进行诊断。常见原因包括端口冲突(检查端口占用情况并修改配置)、权限问题(检查服务运行用户权限)、配置文件错误(检查参数设置)、数据目录损坏(恢复数据或重建表空间)、InnoDB表空间问题(检查ibdata1文件)、插件加载失败(检查错误日志)。解决问题时应根据错误日志进行分析,找到问题的根源,并养成定期备份数据的习惯,以预防和解决问题。

MySQL使用共享锁和排他锁管理并发,提供表锁、行锁和页锁三种锁类型。行锁可提高并发性,使用FOR UPDATE语句可给行加排他锁。悲观锁假设冲突,乐观锁通过版本号判断数据修改。常见锁表问题表现为查询缓慢,使用SHOW PROCESSLIST命令查看锁持有的查询。优化措施包括选择合适索引、减少事务范围、批量操作和优化SQL语句。

MySQL数据库操作中,字符串处理是不可避免的环节。SUBSTRING_INDEX函数正是为此而设计的,它能高效地根据分隔符提取子字符串。SUBSTRING_INDEX函数应用示例以下示例展示了SUBSTRING_INDEX函数的灵活性和实用性:从URL中提取特定部分例如,提取域名:SELECTSUBSTRING_INDEX('www.mysql.com','.',2);提取文件扩展名轻松获取文件扩展名:SELECTSUBSTRING_INDEX('file.pdf','.',-1);处理不存在

对于生产环境,通常需要一台服务器来运行 MySQL,原因包括性能、可靠性、安全性和可扩展性。服务器通常拥有更强大的硬件、冗余配置和更严格的安全措施。对于小型、低负载应用,可在本地机器运行 MySQL,但需谨慎考虑资源消耗、安全风险和维护成本。如需更高的可靠性和安全性,应将 MySQL 部署到云服务器或其他服务器上。选择合适的服务器配置需要根据应用负载和数据量进行评估。

MySQL 和 MariaDB 可以共存,但需要谨慎配置。关键在于为每个数据库分配不同的端口号和数据目录,并调整内存分配和缓存大小等参数。连接池、应用程序配置和版本差异也需要考虑,需要仔细测试和规划以避免陷阱。在资源有限的情况下,同时运行两个数据库可能会导致性能问题。
