最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to multiply BigInt with float? - Stack Overflow

programmeradmin1浏览0评论

What I thought at first to be a simple problem turns out to be a brain teaser.

The problem I am trying to solve is:

  • I have two inputs provided as text
  • They both can be either a bigint or a float with many numbers of the decimal point
  • I need to multiply these numbers and produce result as a text (this seems like the only safe option)

Example inputs are:

8958492893478927347298532876489239230849283
0.00000000000023432787489723234848392840923
327984234.4389057390485483859083482390849028390493037

What's the best way to approach solving this problem?

What I thought at first to be a simple problem turns out to be a brain teaser.

The problem I am trying to solve is:

  • I have two inputs provided as text
  • They both can be either a bigint or a float with many numbers of the decimal point
  • I need to multiply these numbers and produce result as a text (this seems like the only safe option)

Example inputs are:

8958492893478927347298532876489239230849283
0.00000000000023432787489723234848392840923
327984234.4389057390485483859083482390849028390493037

What's the best way to approach solving this problem?

Share Improve this question asked May 18, 2021 at 21:01 GajusGajus 74k80 gold badges297 silver badges472 bronze badges 4
  • You may have issues due to the amount of decimal places, this post may clarify stackoverflow./questions/54800022/… – Marco Arruda Commented May 18, 2021 at 21:05
  • You can just implement mathematical operations that work on strings or arrays of numbers without converting to a number, so you never lose precision. But...it's probably easier to get a library that implements safe mathematical operations for you. – VLAZ Commented May 18, 2021 at 21:23
  • At first, I tried solving this by manipulating the string to convert floats to bigint, do the math, and the convert back. However, ran into a ton of edge cases. I ended up using npmjs./package/exact-math – Gajus Commented May 18, 2021 at 21:35
  • 1 Use an ExactDecimal/BigDecimal library – Bergi Commented May 19, 2021 at 1:22
Add a ment  | 

2 Answers 2

Reset to default 4

I think this should work. The idea is:

1.- Converting the numbers to BigInt and saving the original number of decimals

2.- Multiply both BigInts and restore the zeros you removed in step 1.

It's important to note that the multiply function considers 4 cases:

The first 3 cases are just meant to allow you to manage bigger integers, preventing any of them to bee higher than the BigInt max length during the multiplications, and lower than 1 during the divisions.

The forth case considers the case when the result would likely be a float, so BigInt can't be used anymore.

Note 1: Remember to regex the inputs to prevent the user to add anything but digits and a single dot.

Note 2: This snippet was successfully tested in Firefox and submitting the x,y and z values as plain strings. For some reason, this snippet thing does not manage well the BigInts.

let x = toInt(document.getElementById("x").value.toString());
let y = toInt(document.getElementById("y").value.toString());
let z = toInt(document.getElementById("z").value.toString());

/* getMultiplier rewritten as arrow function, thanks to Bergi */
var getMultiplier = e => 10n ** BigInt(e)

let xy = multiply(x, y)
let xz = multiply(x, z)
let yz = multiply(y, z)

console.log(xy);
console.log(xz);
console.log(yz);

function multiply(a, b) {
    let multiplier = getMultiplier(a["dec"]) * getMultiplier(b["dec"])
    let ab;
    if ((a["int"] > b["int"]) && (a["int"].toString().length > multiplier.toString().length)) {
        ab = a["int"] / multiplier * b["int"]
    } else if ((b["int"] > a["int"]) && (b["int"].toString().length > multiplier.toString().length)) {
        ab = b["int"] / multiplier * a["int"]
    } else if ((b["int"].toString().length + a["int"].toString().length) > multiplier.toString().length) {
        ab = a["int"] * b["int"] / multiplier
    } else {
        let missing = multiplier.toString().length - (b["int"].toString().length + a["int"].toString().length) + 1
        ab = a["int"] * b["int"] * getMultiplier(missing) / multiplier
        /* This number can't be Integer anymore, so we transform the bigint into number */
        ab = Number(ab) / Number(getMultiplier(missing))
    }
    return ab
}

function toInt(e) {
    let eArray = e.split(".")
    let pair = [];
    pair["int"] = BigInt(eArray[0] + (eArray[1] ? eArray[1] : ""))
    pair["dec"] = (eArray[1] ? eArray[1].length : 0)
    return pair
}
<input type="text" id="x" value="8958492893478927347298532876489239230849283">
<input type="text" id="y" value="0.00000000000023432787489723234848392840923">
<input type="text" id="z" value="327984234.4389057390485483859083482390849028390493037">

npm big.js, link: https://www.npmjs./package/big.js?activeTab=readme

const a = Big('123.123')
const b = Big('345345123123')
const c = a.times(b)
发布评论

评论列表(0)

  1. 暂无评论