如何处理JavaScript 中的货币值?

企业动态
无论在银行应用程序、电子商务网站还是证券交易所平台,我们每天都在与金钱互动。我们也越来越依赖技术来处理问题。

金钱无处不在。

无论在银行应用程序、电子商务网站还是证券交易所平台,我们每天都在与金钱互动。我们也越来越依赖技术来处理问题。

然而,关于如何以编程处理货币价值尚无共识。虽然金钱是现代社会中普遍存在的概念,但相较于日期和时间之类的东西,它并不是任何主流语言中的***数据类型。结果,每一种软件都有自己的处理方式,且伴随着陷阱。

陷阱#1:金钱仅仅是数字?

当你需要代表钱时,你的***直觉可能是使用一个数字。

金钱只不过是一个数值,对吧?

错了。

货币价值的一部分与另一对象有关:货币。没有10“钱”,应该是“10美元,10欧元,10比特币”......如果你想用不同的货币添加两个货币值,你需要先转换它们。如果你想比较它们也是如此:如果你只有一个金额,你就无法进行准确的比较。金额和货币谁也离不开谁。

陷阱#2:让人烦恼的小数点

大多数现代货币额都是以小数形式出现,或根本没有子单位。这意味着当货币有子单位时,主单位中这些单位的数量是10的幂。例如,一美元有100美分——10的2次幂。

使用十进制系统具有优势,但在编程方面有一个问题。计算机使用二进制系统,因此它们不能原生地表示十进制数。有些语言提出了自己的解决方案,如Java中的BigDecimal类型或C#中的小数类型。JavaScript只有Number类型,可以用作整数或双精度浮点数。因为它是基础10系统的二进制表示,所以当你尝试进行数学运算时,最终会得到不准确的结果。

使用浮点来存储货币价值是一个坏主意。

当你计算更多值时,难以察觉的精度误差会导致更大的差异。这不可避免地导致最终的四舍五入问题。

陷阱#3:百分比与分配

编程人员应该怎么办?

幸运的是,软件工程师Martin Fowler提出了一个解决方案。在企业应用程序架构模式中,他描述了货币价值的模式:

属性

方法

数学:加,减,乘,除

比较:等于,大于,大于或等于,小于,小于或等于。

由此,你可以创建满足大部分货币需求的价值对象。

“金额+货币”作为数据结构

金钱的行为与简单的数字不同,因此应区别对待。***个也是最重要的是:它应该始终由金额和货币组成。

你可以将货币金额一起添加,检查它们的值是否相对应,并将它们格式化为你需要的任何内容。这可以通过对象的方法完成。在JavaScript中,任何返回对象的函数都可以解决问题。

以分计额

有几种方法可以解决JavaScript中的浮点问题。

你可以使用像Decimal.js这样的库来将浮点数作为字符串。这不是一个糟糕的解决方案,当你必须处理大数字时,它会派上用场。然而,它以增重依赖性为代价,导致性能降低。

你可以在计算之前将浮点数乘以整数,然后将它们分开。

 

这是一个很好的解决方案,但需要在对象构造或每次操作时进行额外的计算。这不一定会影响性能,但仍然需要更多的流程工作。

第三种方法是直接以美分为单位存储相对于单位的值。如果你需要存储10美分,则不会存储0.1,而是10.这允许你仅使用整数,这意味着安全计算(直到你遇到大数字)和出色的性能。

Dinero.js:一个用于创建、计算和格式货币价值的不可变库

从以上观察中,我创建了一个JavaScript库:Dinero.js。

 

Dinero.js遵循Fowler的模式更多一点儿。它允许你在JavaScript中创建、计算和格式化货币值。你可以进行数学运算、解析和格式化对象,甚至向他们提问,使你的开发过程更加轻松。

该库设计为不可变和可链接的模式。它支持全局设置,具有扩展格式选项,并提供本机国际化支持。

为什么不可变?

不可变库更安全,更好预测。可变操作和引用副本是许多错误的来源。选择不变性能够避免了这些错误。

使用Dinero.js,你可以执行计算而无需担心更改原始用例。在以下Vue.js示例中,调用priceWithTax时不会更改Price。如果用例是可变的,它将会更改价格。

 

可链接性

优秀的开发人员努力使他们的代码更简洁,更易于阅读。当你想要在单个对象上连续执行多个操作时,链接提供了优雅的符号和简洁的语法。

 

全球设置

当你处理大量货币价值时,你可能希望其中一些人分享一些属性。如果你使用德语制作网站,你可能希望以德国货币格式显示金额。

这是全球设置派上用场的地方。你可以声明将应用于所有新对象的选项,而不是将它们传递给每个用例。

 

原生国际化支持

传统意义上,库使用区域设置文件进行国际化。

 

区域设置文件也很难维护。 Internationalization API是原生的,并且得到了很不错的支持。除非你必须使用过时的或不知名的浏览器,否则toFormat可以安全使用。

形成格式

对象很适合存储数据,但在显示数据时却没那么有用。Dinero.js提供了各种格式化方法,包括toFormat。它为Number.prototype.toLocaleString提供了直观而简洁的语法。将它与setLocale配对,你将能够以任何语言将任何Dinero对象显示为正确的格式。这对多语言电子商务网站特别有用。

接下来做什么?

大家广泛认同Fowler模式是一个不错的解决方案。它激发了许多语言的同步实现。如果你正在DIY,我推荐它和本文的观察结果作为起点。或者你可以选择Dinero.js:一种现代,可靠,经过全面测试的解决方案,已经可以使用。

本文译自Medium上Sarah Dayan的博文:https://medium.freecodecamp.org/how-to-handle-monetary-values-in-javascript-3fef5eeb3eda

【本文是51CTO专栏作者数据星河的原创文章,作者微信公众号数据星河(ID:BDG-store)】

 

戳这里,看该作者更多好文

 

责任编辑:武晓燕 来源: 51CTO专栏
相关推荐

2017-10-26 08:43:18

JavaScript内存处理

2023-03-09 12:21:38

2011-04-11 17:10:16

Oracle

2019-11-08 08:00:00

ASP .NETASP .NET Cocookie

2021-08-18 08:20:14

SQL除数统计

2012-07-30 09:35:10

项目管理

2019-08-15 10:20:19

云计算技术安全

2021-03-24 10:40:26

Python垃圾语言

2011-01-21 16:27:43

NagiosSendmail

2017-03-13 13:21:34

Git处理大仓库

2012-12-12 09:49:41

2020-12-29 09:11:33

LinuxLinux内核

2021-02-02 07:52:02

CSS短内容长内容

2019-02-25 08:35:22

机器学习数据模型

2011-12-15 12:32:19

JavaNIO

2019-12-23 10:20:12

Web图片优化前端

2021-03-01 07:31:53

消息支付高可用

2014-11-10 10:52:33

Go语言

2012-08-29 10:12:13

人才创业硅谷

2023-04-06 15:19:51

点赞
收藏

51CTO技术栈公众号