使用JS处理资金
使用JS处理资金
使用JS处理资金
本文介绍了使用 JS 处理货币值的不同方法,并推荐了一些库和一个自定义实现。
我制作这个项目是因为我认为有必要展示 JS 如何成为处理资金的系统中可靠的技术。JS 在处理数字方面并没有很好的声誉,这部分是由于浮点运算中的某些不准确性造成的。
起源:
想必大家都见过这个例子:0.1 + 0.2 = 0.30000000000000004,哇,这真是罕见,简直匪夷所思!但为什么会这样呢?这是因为IEEE 754 标准,该标准提倡使用浮点二进制数
。关于这个标准我就不多赘述了,网上已经有很多相关的链接,
我只列出几个。
这种情况只发生在 JavaScript 中吗?
不!这种情况在 Python 和 Java 中也同样会发生:
Python代码:
Python中也存在同样的情况。
Java 代码:
JAVA中也存在同样的情况!!
感到惊讶吗?
这两种语言处理数字都很可靠,当然!JavaScript 也一样。它们都使用 IEEE 754 标准。
如何理财?
使用十进制和浮点数是最佳方法吗?我认为从本质上讲,这是最自然的
方法,但 由于这种标准的精度不足和舍入误差,它未必是最佳方法。您可以在这里了解更多相关信息:
https : //husobee.github.io/money/float/2016/09/23/never-use-floats-for-currency.html
例如:
我以每个 1.40 美元的价格卖出了 165 个苹果。我的会计软件使用浮点数进行计算。
>>> 165 * 1.40
230.99999999999997
正如这个例子所示,你需要自行进行四舍五入才能得到正确的数字。另一个常见的例子是,你将香蕉的价格从 1.01 美元改为 0.99 美元,需要计算由此造成的收入损失。
>>> 1.01 - 0.99
0.020000000000000018
那我该怎么办?
Martin Fowler 创建了一种模式(https://martinfowler.com/eaaCatalog/money.html),其中
金钱被视为一种数据类型,而不仅仅是一个简单的数字。
有一种方法可以解决这些问题,它很简单,或许不是最佳方案,但开发起来容易,
而且有效。我们可以将十进制值转换为以分为单位的表示形式。这样就避免了
浮点运算的细节。
EXPECTED RESULT
===============
1 === $0.01;
10 === $0.10;
100 === $1.00;
1000 === $10.00;
10000 === $100.00;
$1.00 * $0.01 === $0.01
$1.00 * $0.10 === $0.10
$1.00 * $1.00 === $1.00
$1.00 * $10.00 === $10.00
使用整数时遇到问题?
- 我们进行额外的手术。
- JS 不提供无限范围的整数 Number.MIN_SAFE_INTEGER 和 Number.MAX_SAFE_INTEGER。
怎么做?
我们需要将 0.2 和 0.1 这两个值相加,如果我们直接用 JS 来实现,我们知道肯定会有问题。
1) 将每个值乘以 100:(0.2 * 100 + 0.1 * 100) = 30 美分。2
) 换算成货币价值:(0.2 * 100 + 0.1 * 100) / 100 = 0.3。
代码:
我们可以通过多种方式使用库,例如:
- Dinero.js,https://dinerojs.com/
- Finance.js,http://financejs.org/
- Money.js,https://www.npmjs.com/package/moneyjs
- Money Safe。https ://github.com/ericelliott/moneysafe
或者我们可以自行进行自定义实现,但如果这样做,我们就需要考虑如何
为这些操作提供支持。目前,我们将避免进行货币转换。
- 和
- 减法
- 分配
- 乘法
- 相同的
- 次要/较少相等
- 大于/大于等于。
在这个链接中,你可以看到我用原生 JavaScript 实现的这个功能:https://github.com/damiancipolat/handle_money_in_js/blob/master/simple_money.js
const {
money,
isEqual,
isGt,
add,
sub,
mul
} = require('./simple_money.js');
const payment = money(100.20);
const loan = money(15000);
const bill = money(6000);
const debth = money(2000.60);
const addRes = add(payment,bill);
console.log(`${payment.number} + ${bill.number} = ${addRes.number}`);
const subRes = sub(loan,debth);
console.log(`${loan.number} + ${debth.number} = ${subRes.number}`);
console.log(`${payment.number} + ${debth.number} = `,isEqual(payment,bill));
console.log(`${payment.number} + ${payment.number} = `,isEqual(payment,payment));
运行:
$ node test.js
100.2 + 6000 = 6100.2
15000 + 2000.6 = 12999.4
100.2 + 2000.6 = false
100.2 + 100.2 = true
魔法本质上由一些基本功能构成:
const Money = (ammount, value) => ammount?{ammount,value:ammount*100}:{ammount:value/100,value};
//Sum function.
const sum = (a,b) => Money(null,a.value+b.value);
//Payment
const payment = Money(30.342141);
//Bill
const bill = Money(30.342141);
//Test
sum(payment,bill) = {ammount: 60.684282, value: 6068.4282}
在简单的系统中,无需进行大规模的资金操作即可处理资金。
弦和金钱。
在一些国家,货币的表示方式并不统一,与美国不同,那么如何处理货币呢?
在前端设置充值字段非常常见。例如,在阿根廷,金额表示为:$100,000.85,其中“.”用作千位分隔符,“,”用于分隔小数点。
在这种情况下,将金额转换为与 JavaScript 相同的格式非常方便。例如,100,000.85 美元转换为 100000.85(保留两位小数),这样我们就可以将其保存到数据库或用于计算。我称之为归一化,请务必记住这一点。
既然我们已经说过应该使用以分表示的货币价值,我们也可以选择以同样的形式将其保存到数据库中或进行运算。
完善:
使用两个数字还是三个数字?实际上,这取决于我们使用的系统,通常情况下,结果会向上取整,并且使用两个数字。Math.floor()。使用便士的优势在于,它比使用小数更能保证结果的准确性。
注意!在 JavaScript 中,整数不是无限的,数值表示可以在这两个值之间进行。
Number.MIN_SAFE_INTEGER = -9007199254740991
Number.MAX_SAFE_INTEGER = 9007199254740991
超出此范围,无法保证结果准确。
继续阅读
这份链接列表是本项目使用的材料,其中包含许多关于 JS 中数字以及如何使用它来处理资金的非常有趣的文章。
数字
- https://youtu.be/MqHDDtVYJRI
- https://medium.com/@sarafecadu/javascript-numbers-and-the-mystery-0s-b087c5cf21e2
- https://medium.com/@sarafecadu/64-bit-floating-point-a-javascript-story-fa6aad266665
- http://2ality.com/2012/04/number-encoding.html
- http://speakingjs.com/es5/ch11.html
- https://2ality.com/2012/03/displaying-numbers.html
- https://2ality.com/2012/02/nan-infinity.html
- https://2ality.com/2012/03/signedzero.html
- https://2ality.com/2012/01/object-plus-object.html
- https://2ality.com/2012/02/js-integers.html
- http://speakingjs.com/es5/ch11.html
钱
- https://stackoverflow.com/questions/2876536/precise-financial-calculation-in-javascript-what-are-the-gotchas
- https://medium.com/@magnusjt/how-to-handle-money-in-javascript-b954d612373c
- https://frontstuff.io/how-to-handle-monetary-values-in-javascript
- https://itnext.io/how-to-build-a-money-data-type-in-javascript-7b622beabe00
- https://husobee.github.io/money/float/2016/09/23/never-use-floats-for-currency.html




