Add Decimal.floor/.ceil

This commit is contained in:
Simon Warta 2022-04-26 17:05:27 +02:00
parent e9d678aa8f
commit fe50198086
3 changed files with 71 additions and 0 deletions

View File

@ -6,6 +6,10 @@ and this project adheres to
## [Unreleased]
### Added
- @cosmjs/math: Add `Decimal.floor` and `Decimal.ceil`.
## [0.28.4] - 2022-04-15
### Added

View File

@ -177,6 +177,42 @@ describe("Decimal", () => {
});
});
describe("floor", () => {
it("works", () => {
// whole numbers
expect(Decimal.fromUserInput("0", 0).floor().toString()).toEqual("0");
expect(Decimal.fromUserInput("1", 0).floor().toString()).toEqual("1");
expect(Decimal.fromUserInput("44", 0).floor().toString()).toEqual("44");
expect(Decimal.fromUserInput("0", 3).floor().toString()).toEqual("0");
expect(Decimal.fromUserInput("1", 3).floor().toString()).toEqual("1");
expect(Decimal.fromUserInput("44", 3).floor().toString()).toEqual("44");
// with fractional part
expect(Decimal.fromUserInput("0.001", 3).floor().toString()).toEqual("0");
expect(Decimal.fromUserInput("1.999", 3).floor().toString()).toEqual("1");
expect(Decimal.fromUserInput("0.000000000000000001", 18).floor().toString()).toEqual("0");
expect(Decimal.fromUserInput("1.999999999999999999", 18).floor().toString()).toEqual("1");
});
});
describe("ceil", () => {
it("works", () => {
// whole numbers
expect(Decimal.fromUserInput("0", 0).ceil().toString()).toEqual("0");
expect(Decimal.fromUserInput("1", 0).ceil().toString()).toEqual("1");
expect(Decimal.fromUserInput("44", 0).ceil().toString()).toEqual("44");
expect(Decimal.fromUserInput("0", 3).ceil().toString()).toEqual("0");
expect(Decimal.fromUserInput("1", 3).ceil().toString()).toEqual("1");
expect(Decimal.fromUserInput("44", 3).ceil().toString()).toEqual("44");
// with fractional part
expect(Decimal.fromUserInput("0.001", 3).ceil().toString()).toEqual("1");
expect(Decimal.fromUserInput("1.999", 3).ceil().toString()).toEqual("2");
expect(Decimal.fromUserInput("0.000000000000000001", 18).ceil().toString()).toEqual("1");
expect(Decimal.fromUserInput("1.999999999999999999", 18).ceil().toString()).toEqual("2");
});
});
describe("toString", () => {
it("displays no decimal point for full numbers", () => {
expect(Decimal.fromUserInput("44", 0).toString()).toEqual("44");

View File

@ -113,6 +113,37 @@ export class Decimal {
};
}
/** Creates a new instance with the same value */
private clone(): Decimal {
return new Decimal(this.atomics, this.fractionalDigits);
}
/** Returns the greatest decimal <= this which has no fractional part (rounding down) */
public floor(): Decimal {
const factor = new BN(10).pow(new BN(this.data.fractionalDigits));
const whole = this.data.atomics.div(factor);
const fractional = this.data.atomics.mod(factor);
if (fractional.isZero()) {
return this.clone();
} else {
return Decimal.fromAtomics(whole.mul(factor).toString(), this.fractionalDigits);
}
}
/** Returns the smallest decimal >= this which has no fractional part (rounding up) */
public ceil(): Decimal {
const factor = new BN(10).pow(new BN(this.data.fractionalDigits));
const whole = this.data.atomics.div(factor);
const fractional = this.data.atomics.mod(factor);
if (fractional.isZero()) {
return this.clone();
} else {
return Decimal.fromAtomics(whole.addn(1).mul(factor).toString(), this.fractionalDigits);
}
}
public toString(): string {
const factor = new BN(10).pow(new BN(this.data.fractionalDigits));
const whole = this.data.atomics.div(factor);