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:
Example inputs are:
8958492893478927347298532876489239230849283
0.00000000000023432787489723234848392840923
327984234.4389057390485483859083482390849028390493037
What's the best way to approach solving this problem?
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 become 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">