Skip to content

Commit

Permalink
Add clamping functions to FixedNumber (#1037).
Browse files Browse the repository at this point in the history
  • Loading branch information
ricmoo committed Sep 10, 2020
1 parent 6e10675 commit 042b74e
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 9 deletions.
46 changes: 38 additions & 8 deletions packages/bignumber/src.ts/fixednumber.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,29 +240,56 @@ export class FixedNumber {
return FixedNumber.fromValue(a.mul(this.format._multiplier).div(b), this.format.decimals, this.format);
}

floor(): FixedNumber {
let comps = this.toString().split(".");

let result = FixedNumber.from(comps[0], this.format);

const hasFraction = !comps[1].match(/^(0*)$/);
if (this.isNegative() && hasFraction) {
result = result.subUnsafe(ONE);
}

return result;
}

ceiling(): FixedNumber {
let comps = this.toString().split(".");

let result = FixedNumber.from(comps[0], this.format);

const hasFraction = !comps[1].match(/^(0*)$/);
if (!this.isNegative() && hasFraction) {
result = result.addUnsafe(ONE);
}

return result;
}

// @TODO: Support other rounding algorithms
round(decimals?: number): FixedNumber {
if (decimals == null) { decimals = 0; }

// If we are already in range, we're done
let comps = this.toString().split(".");

if (decimals < 0 || decimals > 80 || (decimals % 1)) {
logger.throwArgumentError("invalid decimal count", "decimals", decimals);
}

// If we are already in range, we're done
let comps = this.toString().split(".");
if (comps[1].length <= decimals) { return this; }

// Bump the value up by the 0.00...0005
const bump = "0." + zeros.substring(0, decimals) + "5";
comps = this.addUnsafe(FixedNumber.fromString(bump, this.format))._value.split(".");

// Now it is safe to truncate
return FixedNumber.fromString(comps[0] + "." + comps[1].substring(0, decimals));
const factor = FixedNumber.from("1" + zeros.substring(0, decimals));
return this.mulUnsafe(factor).addUnsafe(BUMP).floor().divUnsafe(factor);
}

isZero(): boolean {
return (this._value === "0.0");
}

isNegative(): boolean {
return (this._value[0] === "-");
}

toString(): string { return this._value; }

Expand Down Expand Up @@ -361,3 +388,6 @@ export class FixedNumber {
return !!(value && value._isFixedNumber);
}
}

const ONE = FixedNumber.from(1);
const BUMP = FixedNumber.from("0.5");
75 changes: 74 additions & 1 deletion packages/tests/src.ts/test-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,80 @@ describe("BigNumber", function() {

});


describe("FixedNumber", function() {
{
const Tests = [
{ value: "0.0", expected: "0.0" },
{ value: "-0.0", expected: "0.0" },

{ value: "1.0", expected: "1.0" },
{ value: "1.00", expected: "1.0" },
{ value: "01.00", expected: "1.0" },
{ value: 1, expected: "1.0" },

{ value: "-1.0", expected: "-1.0" },
{ value: "-1.00", expected: "-1.0" },
{ value: "-01.00", expected: "-1.0" },
{ value: -1, expected: "-1.0" },
];

Tests.forEach((test) => {
it (`Create from=${ test.value }`, function() {
const value = ethers.FixedNumber.from(test.value);
assert.equal(value.toString(), test.expected);
});
});
}

{
const Tests = [
{ value: "1.0", round: 1, expected: "1.0" },
{ value: "1.4", round: 1, expected: "1.4" },
{ value: "1.4", round: 2, expected: "1.4" },
{ value: "1.4", round: 0, expected: "1.0" },
{ value: "1.5", round: 0, expected: "2.0" },
{ value: "1.6", round: 0, expected: "2.0" },

{ value: "-1.0", round: 1, expected: "-1.0" },
{ value: "-1.4", round: 1, expected: "-1.4" },
{ value: "-1.4", round: 2, expected: "-1.4" },
{ value: "-1.4", round: 0, expected: "-1.0" },
{ value: "-1.5", round: 0, expected: "-1.0" },
{ value: "-1.6", round: 0, expected: "-2.0" },

{ value: "1.51", round: 1, expected: "1.5" },
{ value: "1.55", round: 1, expected: "1.6" },
];

Tests.forEach((test) => {
it (`Rounding value=${ test.value }, decimals=${ test.round }`, function() {
const value = ethers.FixedNumber.from(test.value).round(test.round);
assert.equal(value.toString(), test.expected);
});
});
}

{
const Tests = [
{ value: "1.0", ceiling: "1.0", floor: "1.0" },
{ value: "1.1", ceiling: "2.0", floor: "1.0" },
{ value: "1.9", ceiling: "2.0", floor: "1.0" },
{ value: "-1.0", ceiling: "-1.0", floor: "-1.0" },
{ value: "-1.1", ceiling: "-1.0", floor: "-2.0" },
{ value: "-1.9", ceiling: "-1.0", floor: "-2.0" },
];

Tests.forEach((test) => {
it (`Clamping value=${ test.value }`, function() {
const value = ethers.FixedNumber.from(test.value);
assert.equal(value.floor().toString(), test.floor);
assert.equal(value.ceiling().toString(), test.ceiling);
});
});
}
});

describe("Logger", function() {
const logger = new ethers.utils.Logger("testing/0.0");

Expand Down Expand Up @@ -658,7 +732,6 @@ describe("Logger", function() {
});
});


/*
describe("Base58 Coder", function() {
it("decodes", function() {
Expand Down

0 comments on commit 042b74e

Please sign in to comment.