货币的浮点精度:在 MySQL 查询 vs PHP vs Javascript 中使用“round”函数

Posted

技术标签:

【中文标题】货币的浮点精度:在 MySQL 查询 vs PHP vs Javascript 中使用“round”函数【英文标题】:Floating point precision for currency: using "round" function in MySQL query vs PHP vs Javascript 【发布时间】:2015-10-18 19:56:17 【问题描述】:

我正在处理美元金额。在 mysql 数据库中,以下字段费用和费率(百分比)为 DECIMAL 类型,精度为 2 位小数。

SELECT ROUND(fee * (1- rate/100))),2 ) as profit
from products

由于查询只是返回值而不是将它们保存在变量中,精度问题*是否仍然存在(php 或 JS 附带)?如果是这样,最好在 PHP 或 JS 中对浮点数进行四舍五入?

*是的,我的意思是保存双精度时出现的精度问题,例如,1.5 可能会保存为 1.49999999

【问题讨论】:

精度问题还存在吗 ahm什么? 您的计算将返回超过两位小数的结果。你用两个。因此,将发生舍入,是的 - 问题仍然存在。在我看来(这不是事实)——最好让数据管理软件——数据库——处理数字。但这确实很难实现,因为您必须在 PHP 中执行计算,因此处理起来非常棘手。问题的核心是你使用的算法必须是一致的。您可以在 N 位小数后四舍五入、向下舍入或截断 - 您必须始终这样做。 简短回答:不要使用浮点值来赚钱。尽可能将货币价值存储为整数。 @Simba 以及更改值的存储如何准确解决舍入不一致的问题? @birdspider 所以如果客户想要让我们说计算 386.74 的 3% 利息,然后将那一半四舍五入,我会怎么做?重新发明数学?如果我真的重新发明它,我将遇到与以前完全相同的问题,刚才我也有一个半生不熟、缓慢、充满错误的数学库。 【参考方案1】:

其他人可能已经提到了这一点,但我想让您知道我在 PHP 中处理货币计算的系统。

我使用整数。问题是我的每个增量都代表了我需要的最高精度。对于我的大多数应用程序,这是百分之一美元或一美分。但是,您可以将其设置为百万分之一或任何您需要的值。

所以在实践中,以百分之一为精度,$.01 表示为 1,$.10 表示为 10,$1.00 表示为 100,依此类推。这确实消除了舍入问题,因为您将只处理整数,因为任何计算的小数部分都将被截断。不过这没关系,因为整数代表了您需要的最高精度。

诚然,这需要更多的开发来处理,但舍入不应该是突然出现的问题之一。

【讨论】:

这似乎很好,直到你需要划分一些东西。说 $10 / 3,即使以整数开头也会给你一个浮点数回到 php 1000/3 嗨,杰夫。谢谢您的答复。它仍然有效,即使有分裂。无论您使用哪种方法,您几乎总是会留下一分钱的一部分。即使使用小数,当将 10.00 美元除以 3 时,您仍然会得到 3.33333333 美元。使用我概述的方法,您最终得到 333.3333333。无论哪种方式,您都必须决定如何处理一分钱的多余部分。如果您欠银行,银行通常会向上取整,如果欠您,银行通常会向下取整。 Stripe 也这样做(所以这实际上必须是一种非常合法的方法):***.com/questions/35326710/…

以上是关于货币的浮点精度:在 MySQL 查询 vs PHP vs Javascript 中使用“round”函数的主要内容,如果未能解决你的问题,请参考以下文章

正确生成浮点型的方法,解决sqlachemy Float浮点型的坑,生成float类型时,长度和精度均为0,导致查询不到结果!

NSDecimalNumber 用于 Swift 中的货币精度 [重复]

在 PHP 中将十进制/双精度/浮点值与 PDO 绑定的最佳方法是啥?

php与mysql的float类型的精度是分别怎么样的

php json_encode 函数造成浮点类型数据出现精度问题

IEEE-754浮点计算精度问题