Skip to content

Instantly share code, notes, and snippets.

@aljopro
Created December 16, 2022 22:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aljopro/712608a7fc4e400b0f770248befe8962 to your computer and use it in GitHub Desktop.
Save aljopro/712608a7fc4e400b0f770248befe8962 to your computer and use it in GitHub Desktop.
Big Decimal
export type BigDecimalCoersable = BigDecimal | string | number | bigint | undefined;
export class BigDecimal {
// Configuration: constants
public static decimalPrecision = 8; // number of decimals on all instances
public static isRounded = true; // numbers are truncated (false) or rounded (true)
protected static shift = BigInt('1' + '0'.repeat(BigDecimal.decimalPrecision)); // derived constant
protected static fromBigInt(value: bigint) {
const result = new BigDecimal();
result.nValue = value;
return result;
}
protected static divRound(dividend: bigint, divisor: bigint) {
const two = BigInt(2);
const zero = BigInt(0);
const roundingValue = BigDecimal.isRounded ? dividend * two / divisor % two : zero;
return BigDecimal.fromBigInt(dividend / divisor + roundingValue);
}
protected nValue: bigint;
constructor(value: BigDecimalCoersable = undefined) {
if (!value) {
this.nValue = BigInt(0);
return;
}
if (value instanceof BigDecimal) {
this.nValue = value.nValue;
return;
}
const [ints, decis] = String(value).split('.').concat('');
this.nValue = BigInt(ints + decis.padEnd(BigDecimal.decimalPrecision, '0')
.slice(0, BigDecimal.decimalPrecision))
+ BigInt(BigDecimal.isRounded && decis[BigDecimal.decimalPrecision] >= '5');
}
add(num: BigDecimalCoersable) {
return BigDecimal.fromBigInt(this.nValue + new BigDecimal(num).nValue);
}
subtract(num: BigDecimalCoersable) {
return BigDecimal.fromBigInt(this.nValue - new BigDecimal(num).nValue);
}
multiply(num: BigDecimalCoersable) {
return BigDecimal.divRound(this.nValue * new BigDecimal(num).nValue, BigDecimal.shift);
}
divide(num: BigDecimalCoersable) {
return BigDecimal.divRound(this.nValue * BigDecimal.shift, new BigDecimal(num).nValue);
}
toString() {
const s = this.nValue.toString().padStart(BigDecimal.decimalPrecision + 1, '0');
const ints = s.slice(0, -BigDecimal.decimalPrecision);
const decis = s.slice(-BigDecimal.decimalPrecision);
return `${ints}.${decis}`.replace(/\.?0+$/, '');
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment