发布于 2026-01-06 2 阅读
0

用JS处理资金 用JS处理资金

使用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


Enter fullscreen mode Exit fullscreen mode

正如这个例子所示,你需要自行进行四舍五入才能得到正确的数字。另一个常见的例子是,你将香蕉的价格从 1.01 美元改为 0.99 美元,需要计算由此造成的收入损失。



>>> 1.01 - 0.99
0.020000000000000018


Enter fullscreen mode Exit fullscreen mode

那我该怎么办?

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


Enter fullscreen mode Exit fullscreen mode

使用整数时遇到问题?

  • 我们进行额外的手术。
  • 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。

代码:

我们可以通过多种方式使用库,例如​​:

或者我们可以自行进行自定义实现,但如果这样做,我们就需要考虑如何
为这些操作提供支持。目前,我们将避免进行货币转换。

  • 减法
  • 分配
  • 乘法
  • 相同的
  • 次要/较少相等
  • 大于/大于等于。

在这个链接中,你可以看到我用原生 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));


Enter fullscreen mode Exit fullscreen mode

运行



$ node test.js
100.2 + 6000 = 6100.2
15000 + 2000.6 = 12999.4
100.2 + 2000.6 =  false
100.2 + 100.2 =  true


Enter fullscreen mode Exit fullscreen mode

魔法本质上由一些基本功能构成:




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}



Enter fullscreen mode Exit fullscreen mode

在简单的系统中,无需进行大规模的资金操作即可处理资金。

弦和金钱。

在一些国家,货币的表示方式并不统一,与美国不同,那么如何处理货币呢?

在前端设置充值字段非常常见。例如,在阿根廷,金额表示为:$100,000.85,其中“.”用作千位分隔符,“,”用于分隔小数点。

在这种情况下,将金额转换为与 JavaScript 相同的格式非常方便。例如,100,000.85 美元转换为 100000.85(保留两位小数),这样我们就可以将其保存到数据库或用于计算。我称之为归一化,请务必记住这一点。

既然我们已经说过应该使用以分表示的货币价值,我们也可以选择以同样的形式将其保存到数据库中或进行运算。

完善:

使用两个数字还是三个数字?实际上,这取决于我们使用的系统,通常情况下,结果会向上取整,并且使用两个数字。Math.floor()。使用便士的优势在于,它比使用小数更能保证结果的准确性。

注意!在 JavaScript 中,整数不是无限的,数值表示可以在这两个值之间进行。

Number.MIN_SAFE_INTEGER = -9007199254740991
Number.MAX_SAFE_INTEGER = 9007199254740991

超出此范围,无法保证结果准确。

继续阅读

这份链接列表是本项目使用的材料,其中包含许多关于 JS 中数字以及如何使用它来处理资金的非常有趣的文章。

数字

文章来源:https://dev.to/damxipo/handle-money-with-js-4a13