How to Deal with Big Numbers in Javascript

Most of numeric values in Solidity smart contracts are expressed using uint256, unfortunately Javascript numbers are always 64-bit floating point. Therefore when you call a function that returns an uint256 you’ll receive a string instead of a Javascript number. Moreover Solidity does not handle floating number so Eth and token amounts are expressed as unsigned integers with a defined number of decimals. For example 18 for Eth.

In order to be able to deal with such big numbers in Javascript we recommend you to use the bignumber.js library.

Installation

The library is the single JavaScript file bignumber.js (or minified, bignumber.min.js).

Inside a browser:

<script src='path/to/bignumber.js'></script>

With Node:

npm install bignumber.js --save

then import the library your code:

const BigNumber = require('bignumber.js');

Usage

Instantiate

You can chose to instanciate a BigNumber from a numeric value, a string or even an hexadecimal value. Read more about the constructor documentation.

let x = new BigNumber(3.141592); //From a numeric value
let y = new BigNumber("3.141592"); //From a string
let z = new BigNumber('0xff'); //From an hexadecimal string

Operations

All basic numeric operations are available as methods: plusminusmultipliedBydividedBy.

x = new BigNumber(0.1)
y = x.plus(0.2)                 // '0.3'
BigNumber(0.7).plus(x).plus(y)  // '1'
x.plus('0.1', 8)                // '0.225'

If you’d like to round your number, you can use the decimalPlaces method with a numeric parameter with the desired number of decimals:

x = new BigNumber(1234.56)
x.decimalPlaces(1)                     // '1234.6'
x.decimalPlaces(0)                     // 1235

Cast to other types

Once you are working with a BigNumber instance, it’s useful to be able to transform it back to a numeric value or a string to pass to your smart contract or user interface.

Back to a JavaScript numeric value:

x = new BigNumber(456.789)
x.toNumber()                    // 456.789

Back to a String:

x = new BigNumber(456.789)
x.toString()                    // "456.789"

When you are converting your big number to a string, it might be useful to use toFixed() to avoid getting a lot of decimal numbers for eg:

y = new BigNumber(3.456)
x.toFixed()                     // '3'
y.toFixed()                     // '3.456'
y.toFixed(0)                    // '3'
x.toFixed(2)                    // '3.46'
y.toFixed(2)                    // '3.46'
y.toFixed(2, 1)                 // '3.45'  (ROUND_DOWN)
x.toFixed(5)                    // '3.45600'
y.toFixed(5)                    // '3.45600'

Tips

When dealing with ERC20 token or ETH amounts you often have to transform a number to get the number of decimals. The shiftedBy function enable you to easily shift the position of the comma by a defined amount. For example you can transform a 18 decimal value returned by a smart contract call to a readable number:

let oneEther = new BigNumber('10000000000000000000')
oneEther.shiftedBy(-18)                     // '1'

And the opposite is achievable by passing a positive value to the shiftedBy function:

let oneEther = new BigNumber(1)
oneEther.shiftedBy(18)                     // '10000000000000000000'

Leave a Reply

Your email address will not be published. Required fields are marked *