Add clamping functions to FixedNumber (#1037).

This commit is contained in:
Richard Moore 2020-09-10 01:16:28 -04:00
parent 6e10675adf
commit 042b74e6ee
No known key found for this signature in database
GPG Key ID: 665176BE8E9DC651
2 changed files with 112 additions and 9 deletions

@ -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; }
@ -361,3 +388,6 @@ export class FixedNumber {
return !!(value && value._isFixedNumber);
}
}
const ONE = FixedNumber.from(1);
const BUMP = FixedNumber.from("0.5");

@ -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");
@ -658,7 +732,6 @@ describe("Logger", function() {
});
});
/*
describe("Base58 Coder", function() {
it("decodes", function() {