@dintero/money

中文文档
1.1.17发布于 2026/10/30MITTypeScriptCommonJS构建来源已验证近 30 天下载 1.7万

快速实例

中文使用文档
文档目录9 节
  1. 特征
  2. 关于钱在javascript / 为什么存在这个库
  3. Javascript中的数字不适合用钱计算
  4. 整分钱都不够
  5. 运送/储存金额作为日记号
  6. 关于金钱的法律业务
  7. 业绩
  8. API 密码
  9. 创建新版本

钱

快速实例

Money.of(2090.5, "EUR").toCurrency("NOK", 8.61).toString(); // 17999.21

Money.of(0.1, "NOK").add(Money.of(0.2, "NOK")).toString(); // 0.30

Money.fromPriceAndQuantity(0.0005, 30, "NOK").toString(); // 0.02

Money.fromPrice(0.001, "NOK").multiply(60).resetDecimals().toString(); // 0.06

Money.of(10, "NOK").distributeBy([1, 1, 1]); // list of moneys: [3.34, 3.33, 3.33]

Money.of(5.5, "NOK").toLocaleString("no-NB"); // 5,50

Money.fromLocaleString("5,50", "NOK", "no-NB").toString(); // 5.50

Money.of(12.5, "NOK")
    .getVat(25, true) // Amount includes VAT
    .toString(); // 2.50

Money.of(10, "NOK")
    .getVat(25, false) // Amount does not include VAT
    .toString(); // 2.50

Money.of("1234567891234567.25", "NOK").toNumber(); // Throws because the number cannot be represented as a double

见此页下方的全阿皮.

特征

  • 基于大.js,任意的基数为十进制. 没有奇怪的结果 由于基础2双.
  • 基本数学和比较
  • 确保特定货币的准确性
  • 在计算中防止混合货币
  • 任意精确地处理价格
  • 从本地打印和剖析
  • 从分数/ 分数/ 分数/ 整分数打印和剖析
  • 圆相模式( 从 big.js.). 例如,四舍五入(银行家四舍五入)
  • 转换为 Javascript 数字时遇到精度损失时投掷
  • 钱物有标签和标签断言. 例如, 包含 Vat= 的标记以知道该数额包含 vat .
  • 一切都是不可改变的
  • 各种倾斜
    • 计算增值税
    • 按零件或重量分配资金(直视师与资金无关)

关于钱在javascript / 为什么存在这个库

Javascript中的数字不适合用钱计算

Javascript使用双浮点数.

在处理资金方面,有好几个问题:

  • 基数2不能准确代表所有基数10(如:0.1+0.2). 这使得一些计算不准确,无论我们选择的精确度如何. 应当指出,这并不意味着我们不能准确地在两个基地之间转换, 虽然应该提及到Fixed( ) 不是精确的转换
  • 双精度不是无限精度. 当我们需要大量数字时,或者需要许多分数的数字(如价格)时,这一点很重要
  • 在javascript中默认四舍五入对负金额是错误的

比较容易以实例显示:

// Without proper rounding, you'll accumulate small errors:
0.1 + 0.2; // => 0.30000000000000004

// With proper rounding, you'll simply get wrong results:
2090.5 * 8.61; // => 17999.204999999998
(2090.5 * 8.61).toFixed(2); // => 17999.20 // should have been 17999.21

// Even if the console.log manages to convert to base 10 for you,
// the number might not be what you think it is inside the double,
// and toFixed doesn't actually convert to base 10 properly.
// (see also https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed)
(8.165).toFixed(2); // => 8.16 // should have been 8.17

// Math.round rounds towards 0, which doesn't make sense with money:
Math.round(-1.5) - // => -1 // Should have been -2 for money
    // toFixed does it the correct way though:
    (1.5).toFixed(0); // => -2 // Say what now

// 16 decimal digits are too much for javascript doubles
// Note how it doesn't really matter whether we're using whole numbers or not
Number(9999999999999999).toString(); // => 10000000000000000 // Too big for most money amounts, so probably fine
Number(999999999999999.9).toString(); // => 999999999999999.9
Number(99999999999999.99).toString(); // => 99999999999999.98
Number(9999999999999.999).toString(); // => 9999999999999.998
Number(999999999999.9999).toString(); // => 999999999999.9999
Number(99999999999.99999).toString(); // => 99999999999.99998
Number(9999999999.999999).toString(); // => 9999999999.999998
Number(999999999.9999999).toString(); // => 999999999.9999999
Number(99999999.99999999).toString(); // => 99999999.99999999
Number(9999999.999999999).toString(); // => 9999999.999999998 // If this was a price we would be in trouble

这个图书馆使用优异的大. js 库进行任意小数( 第 10 个基数) 算术. 这自动处理上述所有问题.

整分钱都不够

人们常说,一个人应该使用货币的"小"单位的整数,例如一整分. 这对运输和储存来说(也许见下文)是完全罚款的,但精确计算则不是罚款的.

这就是为什么:

  • 你还得分 师会引入小数
  • 您仍然必须转换货币, 利率有小数.
  • 你仍然需要处理价格, 这些可以有任意的小数. 您需要大写来对付那些 因为Javascript只有53个位数(15个小数)可用于整数.
  • 您可能还需要在某个时间点转换到和从小数位转换,而.toFixed()并不准确
  • 您必须跟踪货币和精确度/ 比例 。 任何错误,你就会失去数量级. 这可能比你想象的更头痛 如果你需要以任意的精确度覆盖价格. 在这种情况下,问题也在于储存和运输.

在这个库中,我们选择使用大.js 来避免所有潜在的陷阱 与整个数字计算.

运送/储存金额作为日记号

双胞胎有53个比特 这是准确的部分. 53个二进制数字相当于15.95个十进制数字,或15个是安全的.

因此,我们有15位数字可以合作。 我们能装多少?

世界GDP约为8*10^13美元,需要14位数字。 一分钱就是16个数字. 因此,在美元中,我们只是能够 将全世界的GDP 以美分计,而不失去精确度.

注意,双胞胎的代词不会改变我们得到的精确数字数, 所以,它并不重要,如果我们把它作为一个整体数字或一个分数存储.

无论如何, Javascript数字很可能 足以用于运输和储存 大多数使用案例, 即使是分数。 然而,有一些潜在的陷阱:

  • JSON标准没有定义数字的精度,由解析器处理. 不过,至少假定双重精确性似乎相当合理.
  • 大多数货币在小数点后有0到4个十进制,但加密货币可以拥有更多的. 这可能导致精确要求上升.
  • 如果你处理价格,所有的赌注是关闭的。 价格可以任意精确.

在选择如何储存和运输之前,你必须知道自己的数字会有多大和精确.

这个图书馆给你一些选择:

  • 作为分数 / 全数
  • 作为正常数字
  • 作为字符串

正如我们所看到的那样,前两个有潜在的问题(尽管不太可能), 但为了减轻风险 如果你遇到这些麻烦 我们一定会破例.

如果你想完全安全,就使用绳子.

钱是用一种货币,它通常有一个主(如美元)和小单位(如分币).

  • 金额不能小于小单位(如半分).
  • 价格可以有任意的精确度,但是在四舍五入之前价格不是钱.
  • 精确规则的一个后果是,金钱不能被平分成块(例如,10美元分成3个块将是[3.34, 3.33, 3.33])
  • 货币数学和比较无法进行。 货币转换为共同货币必须先行进行.

这个库确保一个人以正确的货币运作,并正确精确地使用给定的货币. 对于中间计算和价格,可以调整精度.

业绩

大.js是相当快和轻量级, 但远未接近 本地数字的性能.

以下代码需要0.06ms左右,而仅添加本身大约是0.02ms: 1

Money.of(Math.random(), "NOK").add(Money.of(Math.random(), "NOK")).toNumber();

这样你就可以在60英尺范围内做大约260个, 或大约800个纯添加. 如果我们在谈论更大的工作, 你可以在5分钟内完成以上3亿.

API 密码

export type AdditionalOptions = {
    decimals?: number; // Override precision
    roundingMode?: RoundingMode; // See big.js rounding modes
    tags?: Partial<Tags>; // Tag your money to keep track of what it represents
};

export declare class Money {
    constructor(data: MoneyInputData);

    /**
     * Create a money object.
     *
     * Amount can be any of number, string, or Big
     * currency is the 3-character currency code (ISO 4217)
     * currency can also be set to UNKNOWN, which gives a precision of 2 decimals.
     *
     * With options you can specify
     * - decimals
     * - roundingMode
     * - tags
     */
    static of(
        amount: NumberInput,
        currency: string,
        options?: AdditionalOptions,
    ): Money;
    /**
     * Instantiate from a string formatted in a certain locale.
     *
     * Examples:
     * no-NB: 11 111,11
     * en-GB: 11,111.11
     * de-DE: 11.111,11
     *
     * Before parsing, non-numeric characters are removed, and the decimal sign is normalized.
     *
     * Locales with unicode numbers are NOT SUPPORTED
     * Example of formats NOT SUPPORTED:
     * ar: ١١٬١١١٫١١
     */
    static fromLocaleString(
        str: string,
        currency: string,
        locale?: string,
        options?: AdditionalOptions,
    ): Money;
    /**
     * Instantiate from a whole number of minor units of the currency (e.g. whole number of cents)
     *
     * Example:
     * Money.fromFractionlessAmount(1000, 'NOK') => 10.00 NOK
     * Money.fromFractionlessAmount(1000, 'NOK', { decimals: 2 }) => 10.00 NOK
     * Money.fromFractionlessAmount(1000, 'NOK', { decimals: 3 }) => 1.000 NOK
     */
    static fromFractionlessAmount(
        amount: number,
        currency: string,
        options?: AdditionalOptions,
    ): Money;
    /**
     * A price has arbitrary precision.
     * This method creates a Money instance with 6 decimals of precision by default.
     * Remember to call .resetDecimals() when you want to go back to a proper Money value.
     */
    static fromPrice(
        price: NumberInput,
        currency: string,
        options?: AdditionalOptions,
    ): Money;
    /**
     * Calculate total money according to a price and quantity.
     * Default precision is 6 decimals.
     */
    static fromPriceAndQuantity(
        price: NumberInput,
        quantity: Factor,
        currency: string,
        options?: AdditionalOptions,
    ): Money;
    /**
     * Sum an array of moneys.
     *
     * If the array is empty, a currency must be specified so that 0 can be returned in that currency.
     *
     * The precision, rounding mode, etc, is based on the first item in the array.
     * If the array is empty, the options object will be used instead.
     */
    static sum(
        moneys: Money[],
        currency?: string,
        options?: AdditionalOptions,
    ): Money;
    static max(moneys: Money[]): Money;
    static min(moneys: Money[]): Money;
    /**
     * Compare two money objects.
     *
     * 1 if money1 is greater than money2
     * 0 if equal
     * -1 if money1 is less than money2
     *
     * This can be plugged directly into array.sort(),
     * and it will cause the array to be sorted in ascending order.
     */
    static compare(money1: Money, money2: Money): number;

    merge: (data: Partial<MoneyInputData>) => Money;

    // Tags
    /**
     * Tags allow you to communicate more about what the money represents.
     * You can later assert on a tag to make sure you're using the right amount for the right purpose.
     */
    getTags: () => Tags;
    getTag: <Name extends keyof Tags, Value>(
        tagName: Name,
        defaultValue?: Value | undefined,
    ) => Value | undefined;
    setTag: <Name extends keyof Tags>(tagName: Name, value: any) => Money;

    // Assertions
    assertTag: <Name extends keyof Tags>(
        tagName: Name,
        value: any,
        cmp?: (actual: any, value: any) => boolean,
    ) => Money;
    assertSameCurrency: (money: Money) => Money;

    // Utils
    amount: () => Big;
    currency: () => string;

    // Converters
    /**
     * Converts the money amount into a whole number given in the minor unit of the currency.
     * Honors the current precision in use.
     */
    toFractionlessAmount: () => number;
    /**
     * Converts to a regular javascript number.
     * Throws an error if it's not possible to do keep full precision.
     */
    toNumber: () => number;
    toString: () => string;
    toLocaleString: (locale?: string | undefined) => string;
    toJSON: () => number;

    /**
     * Gets the current precision in use.
     */
    getDecimals: () => number;
    /**
     * Override the default precision of the currency.
     * Useful if you're working with a price.
     */
    setDecimals: (decimals: number) => Money;
    /**
     * Reset precision back to that of the currency.
     * Useful for converting from a price to the final monetary amount.
     */
    resetDecimals: () => Money;
    /**
     * Converts to a different currency using a currency rate.
     * Sometimes (rarely) the rate is given multiplied by a certain unit amount which has to be divided away.
     */
    toCurrency: (
        currency: string,
        currencyRate?: Factor,
        currencyUnit?: Factor,
    ) => Money;

    //Math
    round: (decimals: number, roundingMode?: RoundingMode | undefined) => Money;
    multiply: (factor: Factor) => Money;
    /**
     * Note that dividing a monetary amount cannot be exact in all cases.
     * E.g. 10 NOK / 3 = 3.33 NOK
     * Use `distribute` or `distributeBy` if you need an exact distribution.
     *
     * The division is performed with a precision of 20 decimals before
     * rounding back to the monetary amount. (See https://mikemcl.github.io/big.js/#dp)
     */
    divide: (divisor: Factor) => Money;
    add: (money: Money) => Money;
    subtract: (money: Money) => Money;
    abs: () => Money;

    // Comparisons
    equals: (money: Money) => boolean;
    greaterThan: (money: Money) => boolean;
    greaterThanOrEqual: (money: Money) => boolean;
    lessThan: (money: Money) => boolean;
    lessThanOrEqual: (money: Money) => boolean;
    isZero: () => boolean;
    /**
     * Positive and not 0
     */
    isPositive: () => boolean;
    /**
     * Negative and not 0
     */
    isNegative: () => boolean;

    // Distribute
    /**
     * Divides money into n parts.
     *
     * Example:
     * Money.of(10, 'NOK').distribute(3) => [3.34, 3.33, 3.33]
     *
     * Distributes any rest amount equally across the parts
     */
    distribute: (nParts: number) => Money[];
    /**
     * Divides money into parts, each defined by a weight.
     *
     * Each weight must be >= 0
     * Total of weights must be > 0
     *
     * Example:
     * Money.of(10, 'NOK').distributeBy([1, 1, 1]) => [3.34, 3.33, 3.33]
     *
     * Distributes any rest amount equally across the parts
     */
    distributeBy: (inputWeights: Factor[]) => Money[];

    // VAT
    addVat: (vatPercentage: Factor) => Money;
    removeVat: (vatPercentage: Factor) => Money;
    getVat: (vatPercentage: Factor, includesVat?: boolean | undefined) => Money;
}

创建新版本

  1. 执行所有对主分支的承诺,按照 角提交信件格式
  2. 当合并为主机时, 它会自动与 语义释放

版本与发布记录

@dintero/money 共发布 38 个版本,首次发布于 2021/09/14;过去 12 个月发布了 16 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
1.1.17latest2026/10/3012 天前
1.1.162026/10/091 个月前
1.1.152026/10/021 个月前
1.1.142026/09/301 个月前
1.1.132026/08/232 个月前
1.1.122026/07/213 个月前

关于 @dintero/money 的常见问题

@dintero/money 是什么?

快速实例

如何安装 @dintero/money?

在项目目录运行 npm install @dintero/money,或使用 pnpm add / yarn add / bun add。

@dintero/money 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@dintero/money 支持 ESM 还是 CommonJS?

以 CommonJS 形式发布,可以直接 require();在 ES Module 项目中也可以用 import 引入(Node.js 会把 module.exports 作为默认导出)。

@dintero/money 可以商用吗?

@dintero/money 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@dintero/money 的下载量有多少?

根据 npm 官方下载统计,@dintero/money 在 2026/10/13 – 2026/11/11 这 30 天内被下载 16,838 次,日均约 561 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@dintero/money 还在维护吗?

最新版本 1.1.17 发布于 2026/10/30(12 天前);至今共发布 38 个版本,其中过去 12 个月发布了 16 个;首次发布于 2021/09/14。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。