Skip to content

Commit

Permalink
Convert to BigInt and Number
Browse files Browse the repository at this point in the history
  • Loading branch information
jessealama committed May 6, 2024
1 parent 10a4b5c commit 81f3c38
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 9 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [14.1.0] - 2024-05-06

### Added

- Support for converting decimals to BigInts and Numbers.

## [14.0.0] - 2024-04-30

### Removed
Expand Down
55 changes: 46 additions & 9 deletions src/decimal128.mts
Original file line number Diff line number Diff line change
Expand Up @@ -668,15 +668,6 @@ const DEFAULT_CONSTRUCTOR_OPTIONS: FullySpecifiedConstructorOptions =
normalize: CONSTRUCTOR_SHOULD_NORMALIZE,
});

interface FullySpecifiedArithmeticOperationOptions {
roundingMode: RoundingMode;
}

const DEFAULT_ARITHMETIC_OPERATION_OPTIONS: FullySpecifiedArithmeticOperationOptions =
Object.freeze({
roundingMode: ROUNDING_MODE_DEFAULT,
});

type ToStringFormat = "decimal" | "exponential";
const TOSTRING_FORMATS: string[] = ["decimal", "exponential"];

Expand Down Expand Up @@ -938,6 +929,52 @@ export class Decimal128 {
return this.emitDecimal(options);
}

private isInteger(): boolean {
let s = this.toString();

let [_, rhs] = s.split(/[.]/);

if (rhs === undefined) {
return true;
}

return !!rhs.match(/^0+$/);
}

toBigInt(): bigint {
if (this.isNaN) {
throw new RangeError("NaN cannot be converted to a BigInt");
}

if (!this.isFinite) {
throw new RangeError("Infinity cannot be converted to a BigInt");
}

if (!this.isInteger()) {
throw new RangeError(
"Non-integer decimal cannot be converted to a BigInt"
);
}

return BigInt(this.toString());
}

toNumber(): number {
if (this.isNaN) {
return NaN;
}

if (!this.isFinite) {
if (this.isNegative) {
return -Infinity;
}

return Infinity;
}

return Number(this.toString());
}

/**
* Compare two values. Return
*
Expand Down
46 changes: 46 additions & 0 deletions tests/tobigint.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { Decimal128 } from "../src/decimal128.mjs";
import { expectDecimal128 } from "./util.js";

describe("NaN", () => {
test("does not work", () => {
expect(() => new Decimal128("NaN").toBigInt()).toThrow(RangeError);
});
});

describe("zero", () => {
test("positive zero", () => {
expect(new Decimal128("0").toBigInt()).toStrictEqual(0n);
});
test("negative zero", () => {
expect(new Decimal128("-0").toBigInt()).toStrictEqual(0n);
});
});

describe("infinity", () => {
test("positive", () => {
expect(() => new Decimal128("Infinity").toBigInt()).toThrow(RangeError);
});
test("negative", () => {
expect(() => new Decimal128("-Infinity").toBigInt()).toThrow(
RangeError
);
});
});

describe("non-integer", () => {
test("throws", () => {
expect(() => new Decimal128("1.2").toBigInt()).toThrow(RangeError);
});
test("work with mathematical value (ignore trailing zeroes)", () => {
expect(new Decimal128("1.00").toBigInt()).toStrictEqual(1n);
});
});

describe("simple examples", () => {
test("42", () => {
expect(new Decimal128("42").toBigInt()).toStrictEqual(42n);
});
test("-123", () => {
expect(new Decimal128("-123").toBigInt()).toStrictEqual(-123n);
});
});
40 changes: 40 additions & 0 deletions tests/tonumber.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Decimal128 } from "../src/decimal128.mjs";
import { expectDecimal128 } from "./util.js";

describe("NaN", () => {
test("works", () => {
expect(new Decimal128("NaN").toNumber()).toStrictEqual(NaN);
});
});

describe("zero", () => {
test("positive zero", () => {
expect(new Decimal128("0").toNumber()).toStrictEqual(0);
});
test("negative zero", () => {
expect(new Decimal128("-0").toNumber()).toStrictEqual(-0);
});
});

describe("infinity", () => {
test("positive infinity", () => {
expect(new Decimal128("Infinity").toNumber()).toStrictEqual(Infinity);
});
test("negative infinity", () => {
expect(new Decimal128("-Infinity").toNumber()).toStrictEqual(-Infinity);
});
});

describe("simple examples", () => {
test("1.25", () => {
expect(new Decimal128("1.25").toNumber()).toStrictEqual(1.25);
});
test("0.1", () => {
expect(new Decimal128("0.1").toNumber()).toStrictEqual(0.1);
});
test("extreme precision", () => {
expect(
new Decimal128("0." + "0".repeat(100) + "1").toNumber()
).toStrictEqual(1e-101);
});
});

0 comments on commit 81f3c38

Please sign in to comment.