Skip to content

Commit

Permalink
:spakles: feat: introduce BigDecimal to boost
Browse files Browse the repository at this point in the history
  • Loading branch information
Leslie-Wong-H committed Aug 21, 2021
1 parent 5b1181d commit 17db611
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 10 deletions.
83 changes: 78 additions & 5 deletions jsbi-calculator.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,83 @@
* @email [email protected]
* @description a calculator utility to perform arbitrary-presion arithmetic in BigDecimal, JSBI based.
*/

"use strict";

import JSBI from "jsbi";

/**
*
* @description A custom BigDecimal class wrapped with JSBI,
* which is inspred from trincot's answer.
* https://stackoverflow.com/a/66939244/8808175
*
*/
class BigDecimal {
// Configuration: constants
static DECIMALS = 18; // number of decimals on all instances
static ROUNDED = true; // number are truncated (false) or rounded (true)
static SHIFT = JSBI.BigInt("1" + "0".repeat(BigDecimal.DECIMALS)); // derived constant
constructor(value) {
if (value instanceof BigDecimal) return value;
let [ints, decis] = String(value).split(".").concat("");
this._n = JSBI.add(
JSBI.BigInt(
ints +
decis.padEnd(BigDecimal.DECIMALS, "0").slice(0, BigDecimal.DECIMALS)
),
JSBI.BigInt(BigDecimal.ROUNDED && decis[BigDecimal.DECIMALS] >= "5")
);
}

static fromJSBIBigInt(jsbibigint) {
return Object.assign(Object.create(BigDecimal.prototype), {
_n: jsbibigint,
});
}
add(num) {
return BigDecimal.fromJSBIBigInt(JSBI.add(this._n, new BigDecimal(num)._n));
}
subtract(num) {
return BigDecimal.fromJSBIBigInt(
JSBI.subtract(this._n, new BigDecimal(num)._n)
);
}
static _divRound(dividend, divisor) {
return BigDecimal.fromJSBIBigInt(
JSBI.add(
JSBI.divide(dividend, divisor),
BigDecimal.ROUNDED
? JSBI.remainder(
JSBI.divide(JSBI.multiply(dividend, JSBI.BigInt(2)), divisor),
JSBI.BigInt(2)
)
: JSBI.BigInt(0)
)
);
}
multiple(num) {
return BigDecimal._divRound(
JSBI.multiply(this._n, new BigDecimal(num)._n),
BigDecimal.SHIFT
);
}
divide(num) {
return BigDecimal._divRound(
JSBI.multiply(this._n, BigDecimal.SHIFT),
new BigDecimal(num)._n
);
}
toString() {
const s = this._n.toString().padStart(BigDecimal.DECIMALS + 1, "0");
return (
s.slice(0, -BigDecimal.DECIMALS) +
"." +
s.slice(-BigDecimal.DECIMALS).replace(/\.?0+$/, "")
);
}
}

/**
* Directly get the result with arbitrary precision using jsbiCal and rpnParse
* @param {String} expression
Expand Down Expand Up @@ -94,29 +167,29 @@ function jsbiCal(tokens) {
case "+": {
let a1 = stack.pop();
let b1 = stack.pop();
stack.push(JSBI.add(b1, a1));
stack.push(new BigDecimal(b1).add(a1));
break;
}
case "-": {
let a2 = stack.pop();
let b2 = stack.pop();
stack.push(JSBI.subtract(b2, a2));
stack.push(new BigDecimal(b2).subtract(a2));
break;
}
case "*": {
let a3 = stack.pop();
let b3 = stack.pop();
stack.push(JSBI.multiply(b3, a3));
let b3_ = stack.push(new BigDecimal(b3).multiply(a3));
break;
}
case "/": {
let a4 = stack.pop();
let b4 = stack.pop();
stack.push(JSBI.divide(b4, a4));
stack.push(new BigDecimal(b4).divide(a4));
break;
}
default:
stack.push(JSBI.BigInt(item));
stack.push(new BigDecimal(item));
}
}
return String(stack.pop());
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "jsbi-calculator",
"version": "0.0.1",
"description": "A calculator utility to perform arbitrary integral arithmetic and exponentiation in BigInt, JSBI based.",
"description": "JSBI-Calculator is a calculator utility to perform arbitrary arithmetic computation, with the help of JSBI-based BigDecimal.",
"main": "dist/jsbi-calculator.js",
"module": "dist/jsbi-calculator.mjs",
"browser": "dist/jsbi-calculator-umd.js",
Expand Down
11 changes: 7 additions & 4 deletions readme.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# JSBI-Calculator

JSBI-Calculator is a calculator utility to perform arbitrary integral arithmetic and exponentiation in BigInt, JSBI based.
JSBI-Calculator is a calculator utility to perform arbitrary arithmetic computation, with the help of JSBI-based BigDecimal.

## Installation

Expand Down Expand Up @@ -56,13 +56,16 @@ console.log(resultTwo);

## Note:

The following operations are available. Please mind the factors which are negative must start with "-"
and be surrounded by parentheses, and positive ones can not start with "+".
The following operations are available. Please mind the factors which are
negative must start with "-" and be surrounded by parentheses, and
positive ones can not start with "+".

| Operation | Symbol |
| -------------- | ------ |
| Addition | `+` |
| Subtration | `-` |
| Multiplication | `*` |
| Division | `/` |
| Exponentiation | `^` |

## Under the hood:

0 comments on commit 17db611

Please sign in to comment.