Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ability to round up/down in multiply and divide operations #13

Merged
merged 11 commits into from
Jun 4, 2024

Conversation

gidonkatten
Copy link
Contributor

The default behaviour for the multiply and divide operations was to ROUND_HALF. Added the possibility to specify whether to ROUND_UP or ROUND_DOWN. Rounding down is especially important as that is the typical behaviour in smart contract opcodes (EVM and non-EVM alike).

Also fixed a bug in the divideAndRound function (which is called by many operations) when the divisor is negative. E.g. divideAndRound(-15n, 2n)) and divideAndRound(15n, -2n) yielded different results.

Updated docs with latest changes.

Copy link
Owner

@bpierre bpierre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding this, it’s looking great! And thanks for fixing the rounding bug 🙏

What would you think of having optionsOrDecimals as a third parameter, following what we are doing with other functions using optionsOrDigits?

Also, would it be worth adding the ability to pass a Rounding to dnum.round()?

src/types.ts Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
src/dnum.ts Outdated Show resolved Hide resolved
src/utils.ts Show resolved Hide resolved
test/all.test.ts Show resolved Hide resolved
@gidonkatten
Copy link
Contributor Author

Thanks @bpierre for looking at the PR, replying to your comments

What would you think of having optionsOrDecimals as a third parameter, following what we are doing with other functions using optionsOrDigits?

Sorry I don't understand what this means, can you elaborate?

Also, would it be worth adding the ability to pass a Rounding to dnum.round()?

Done :)

@gidonkatten
Copy link
Contributor Author

Actually I now realise the library already has floor and ceil functions so not sure how much value adding ROUND_UP and ROUND_DOWN to dnum.round() brings. Feel free to suggest to remove it if you prefer

src/types.ts Outdated Show resolved Hide resolved
@bpierre
Copy link
Owner

bpierre commented Jun 2, 2024

What would you think of having optionsOrDecimals as a third parameter, following what we are doing with other functions using optionsOrDigits?

Sorry I don't understand what this means, can you elaborate?

I mean doing this:

export function divide(
  num1: Numberish,
  num2: Numberish,
  optionsOrDecimals?: Decimals | {
    decimals?: Decimals,
    rounding?: Rounding,
  } = {},
): Dnum {
  const options = typeof optionsOrDecimals === "number"
    ? { decimals: optionsOrDecimals }
    : optionsOrDecimals

  options.rounding ??= "ROUND_HALF"
  // …
}

To follow the API of e.g. format():

export function format(
  dnum: Dnum,
  // see toParts() in src/dnum.ts
  optionsOrDigits: Parameters<typeof toParts>[1] & {
    compact?: boolean;
    locale?: ConstructorParameters<typeof Intl.NumberFormat>[0];
    signDisplay?: SignDisplay;
  } = {},
): string {
  const options = typeof optionsOrDigits === "number"
    ? { digits: optionsOrDigits }
    : optionsOrDigits;
  // …

The general idea being to pick one option from the options object and allow it to be passed directly as a shortcut.

Also, would it be worth adding the ability to pass a Rounding to dnum.round()?

Done :)
Actually I now realise the library already has floor and ceil functions so not sure how much value adding ROUND_UP and ROUND_DOWN to dnum.round() brings. Feel free to suggest to remove it if you prefer

It does yes, but I thought it could be nice to allow using Rounding here too, and have ceil() and floor() as aliases? Or do you think it will just add confusion?

@gidonkatten
Copy link
Contributor Author

What would you think of having optionsOrDecimals as a third parameter, following what we are doing with other functions using optionsOrDigits?

Okay I understand now - I don't really have a preference. I followed what you had done for setDecimals where the decimals and options were seperated.

It does yes, but I thought it could be nice to allow using Rounding here too, and have ceil() and floor() as aliases? Or do you think it will just add confusion?

I agree it's probably a nice thing to have and I don't see it being confusing. Now that you mentioned it, I simplified ceil and floor functions to call round.

@bpierre
Copy link
Owner

bpierre commented Jun 2, 2024

Okay I understand now - I don't really have a preference. I followed what you had done for setDecimals where the decimals and options were seperated.

Thinking more about it, I think it would be weird to require consumers to set decimals (or explicitly pass undefined) in order to set options.rounding. Let’s go with optionsOrDecimals in multiply(), divide() and round(), if you don’t mind making the change 🙏

It does yes, but I thought it could be nice to allow using Rounding here too, and have ceil() and floor() as aliases? Or do you think it will just add confusion?

I agree it's probably a nice thing to have and I don't see it being confusing. Now that you mentioned it, I simplified ceil and floor functions to call round.

Nice! We might even end up with a smaller size than before 😄

@gidonkatten
Copy link
Contributor Author

gidonkatten commented Jun 3, 2024

@bpierre I updated the three operations with optionsOrDecimals like you suggested. The README needs to be updated with the new parameter, how would you advise to do this?

@bpierre
Copy link
Owner

bpierre commented Jun 3, 2024

@gidonkatten looking good!

For the docs: maybe we could do it the same way as format(), where options.digits says this:

“Setting options to a number acts as an alias for this option (see example below).”.

@gidonkatten gidonkatten requested a review from bpierre June 4, 2024 08:12
Copy link
Owner

@bpierre bpierre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot @gidonkatten 🙏

@bpierre bpierre merged commit 1f07c9d into bpierre:main Jun 4, 2024
@gidonkatten gidonkatten deleted the feature/rounding branch June 4, 2024 19:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants