如何在 PHP 中安全地执行与金钱相关的计算?
我正在编写一些报告输出脚本,需要对一些货币值进行一些基本计算。
我知道浮点算术用于此目的的局限性,但是输入值都是十进制格式,因此如果我对它们使用算术运算符,PHP 会将它们转换为浮点数。
那么处理这些数字的最佳方法是什么? 我应该使用 BCMath 吗? .NET 中是否有类似于 Decimal 的东西? 或者如果我强制转换回 int,使用算术运算符是否安全?
I'm working on a few report output scripts that need to do some rudimentary calculations on some money values.
I am aware of the limitations of floating point arithmetic for this purpose, however the input values are all in a decimal format, so if I use the arithmetic operators on them PHP will cast them to floats.
So what is the best way to handle the numbers? Should I use BCMath? Is there something akin to Decimal in .NET? Or is it safe to use the arithmetic operators if I cast back to int?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
不要以美元 ($1.54) 为单位,以美分 (154c) 为单位。 除非您需要执行的任务中一美分的一小部分很重要,否则您将使用整数,一切都很好。 如果您对十分之一美分感兴趣,那么只需将所有内容乘以十即可!
Don't work in Dollars ($1.54), work in cents: (154c). Unless you need to be performing tasks where fractions of a cent are important, then you'll be working with integers and all is well. If you are interested in tenths of a cent, then just multiply everything by ten!
如果您使用 BCMath,所有值都将存储在字符串中并作为字符串传递给函数,就像结果将是字符串一样。 因此,您不需要进行任何转换,但要确保提供给函数的数字是一个数值。 就个人而言,如果数学需要小数点的高精度,那么请使用 BCMath。
If you use BCMath all values will be stored in strings and passed to the functions as strings, just as the result will be a string. So, you needn't do any casting but ensure that the number given to the function is a value numeric value. Personally, if the math requires a high amount of precision on the decimal side then use BCMath.
如果您使用合理的金额(对于“正常人”),那么使用浮点不太可能成为问题,特别是如果您只是添加和减去金额,而不是进行利息计算等操作。
如果您正在寻找快速解决方案,那么切换到整数不太可能对您有帮助; 你仍然需要处理溢出问题。 (这里有人编辑提到,如果 PHP 遇到超出整数类型范围的数字,将会被解释为但是随后您又回到了使用浮点的原始问题!)任意长度整数(GMP,从该页面引用)可以提供帮助。)
基本上,以半途而废的方式执行此操作可以在大多数情况下,而且价格便宜; 正确地做到这一点是一种严重的痛苦。 我的建议是将其视为一个业务问题:如果有人抱怨少了一分钱,就给他们一美元,并且不要费心开始真正的解决方案,直到您可以通过这样做节省更多美元。
If you're working with reasonable amounts (to a "normal person"), using floating point is not likely to be a problem, especially if you're just adding and subtracting amounts, rather than doing, say, interest calculations.
If you're looking for a quick fix, switching to integer is not likely to help you; you still have to deal with overflow. (Someone edited here to mention that if PHP encounters a number beyond the bounds of the integer type, it will be interpreted as a float instead. But then you're back to your original problem of using floating point!) Arbitrary length integers (GMP, referenced from that page) can help.)
Basically, doing this in a half-assed way works in most cases, and is cheap; doing it correctly is a serious pain. My suggestion is to look at this as a business problem: if someone complains about missing a cent, give them a dollar, and don't bother starting on a real solution until you're going to save more dollars by doing that.