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

Does BigNumber only support Integers? (answer: yes) #488

Closed
thanhvk opened this issue Apr 11, 2019 · 2 comments
Closed

Does BigNumber only support Integers? (answer: yes) #488

thanhvk opened this issue Apr 11, 2019 · 2 comments
Labels
discussion Questions, feedback and general information.

Comments

@thanhvk
Copy link

thanhvk commented Apr 11, 2019

Hi everyone,

I have code as below:

export const computeChange = (open: string, close: string) => {
    const bigOpen = utils.bigNumberify(open)
    const bigClose = utils.bigNumberify(close)
    const percentMultiplier = utils.bigNumberify(100)

    if (bigOpen.eq(bigClose)) return 0

    const change = ((bigClose.sub(bigOpen)).mul(percentMultiplier)).div(bigOpen)
    return change
}

in case open = 252350000000000000000000000000000000000, close = 252320000000000000000000000000000000000

const change = ((bigClose.sub(bigOpen)).mul(percentMultiplier)).div(bigOpen) return 0 instead 0.011889663918834626.

So what I do wrong in here? or this is bug? and Do you have any experience or solution for this issue?

Thank you!

@ricmoo
Copy link
Member

ricmoo commented Apr 11, 2019

BigNumber is only for integers, it does not support floating-point or fixed-point math. In v5 (public beta soon) there is a FixedPoint object to help with these, but in the meantime, you can use the formatUnits to do this.

Keep in mind that floating-point numbers in JavaScript are NOT precise. They cannot be, it is not possible to represent arbitrary precision with a fixed number of bits (i.e. 64 bits)

You will need to choose a resolution you wish the result to be accurate to, but you can for example use:

// Multiply by 1000 to keep 3 decimal places
const change = ((bigClose.sub(bigOpen)).mul(percentMultiplier)).mul("1000").div(bigOpen);
// We use 2 here for decimals, since we multiplied by 1000 above.
const changeString = ethers.utils.formatUnits(change, 3);

In general though, if you plan to use decimal numbers there will be a lot of consequences you should familiarize yourself with regarding rounding, underflow (completely unrelated to overflow), parsing/formatting and representation.

@ricmoo ricmoo added the discussion Questions, feedback and general information. label Apr 11, 2019
@ricmoo ricmoo changed the title BigNumber return wrong result Does BigNumber only support Integers? (answer: yes) Apr 11, 2019
@ricmoo
Copy link
Member

ricmoo commented May 24, 2019

Closing this now, but if you have more questions, please feel free to re-open or continue discussion (I monitor closed issues).

In v5, there is a FixedNumber type which can be used to perform fixed-point math operations too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
discussion Questions, feedback and general information.
Projects
None yet
Development

No branches or pull requests

2 participants