【问题标题】:How to divide two native JavaScript BigInt's and get a decimal result如何将两个原生 JavaScript BigInt 相除并得到十进制结果
【发布时间】:2019-06-21 22:04:23
【问题描述】:

这是我迄今为止尝试过的。我正在寻找12.34:

BigInt('12340000000000000000') / BigInt('1000000000000000000')

12n

Number(BigInt('12340000000000000000') / BigInt('1000000000000000000'))

12

FWIW,当我使用 JSBI 库时,它的工作方式是我想要的:

JSBI.BigInt('12340000000000000000') / JSBI.BigInt('1000000000000000000');

12.34

这在本地是不可能的吗?

【问题讨论】:

  • Number(BigInt('x')) / Number(BigInt('y')) 怎么样 - 即两个原生数字的普通原生除法?
  • 否则,据我所知,你不能这样做,因为 BigDecimal 与 Java 中的 BigInteger 没有任何关系
  • @Pointy Number(BigInt('12340000000000000001')) 不起作用,因为使用 BigInt 的全部目的是保持完整的精度,如果将其转换为数字,则会丢失。结果将是12340000000000000000
  • @Pointy 对于您的第二条评论...是的,我想这可能不可行,但奇怪的是官方推荐作为后备的库可以做到这一点
  • JSBI 中的等价物是JSBI.divide('12340000000000000000', '1000000000000000000')

标签: javascript biginteger bigint


【解决方案1】:

您应该乘以分子以适应您需要的位数,执行除法,然后用普通浮点除法除。

(在支持 BigInt 的浏览器中运行,如 Chrome)

var a = 12340000000000000000n;
var b =  1000000000000000000n;

console.log(Number(a * 100n / b) / 100);

仅在“末尾”转换为数字,您将损失最少的精度。

更精确

如果您需要超过 16 位的精度并且需要小数,那么您需要自己实现一种 BigDecimal API,或者使用现有的。

这是一个简单的,使用BigInt 作为其基本类型,并结合了一个配置,该配置确定每个此类 BigInt 的多少位(从右侧)应解释为小数(小数部分中的数字)。例如,在将数字输出为字符串时,最后的信息将用于插入小数分隔符。

class BigDecimal {
    constructor(value) {
        let [ints, decis] = String(value).split(".").concat("");
        decis = decis.padEnd(BigDecimal.decimals, "0");
        this.bigint = BigInt(ints + decis);
    }
    static fromBigInt(bigint) {
        return Object.assign(Object.create(BigDecimal.prototype), { bigint });
    }
    divide(divisor) { // You would need to provide methods for other operations
        return BigDecimal.fromBigInt(this.bigint * BigInt("1" + "0".repeat(BigDecimal.decimals)) / divisor.bigint);
    }
    toString() {
        const s = this.bigint.toString().padStart(BigDecimal.decimals+1, "0");
        return s.slice(0, -BigDecimal.decimals) + "." + s.slice(-BigDecimal.decimals)
                .replace(/\.?0+$/, "");
    }
}
BigDecimal.decimals = 18; // Configuration of the number of decimals you want to have.

// Demo
var a = new BigDecimal("123456789123456789876");
var b = new BigDecimal( "10000000000000000000");

console.log(a.divide(b).toString());

同样,这需要支持BigInt(撰写本文时的Chrome)的浏览器。

【讨论】:

  • 查看我的答案。
  • @noririco,它在typescript 中给出相同的输出:“12.345678912345678987”
  • @trincot 谢谢!我的错误是static decimals = 18; 不是static
  • 原因是toString中的字符串s没有足够的位数在正确的位置注入小数点。现在修好了。感谢您发现这一点。
  • 仅供参考,我有一个带有加、减、乘和舍入的版本作为BigDecimal in JavaScript 的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-26
  • 1970-01-01
  • 2019-01-15
  • 1970-01-01
  • 2017-04-28
  • 2021-09-03
  • 1970-01-01
相关资源
最近更新 更多