# ethers formatEther(wei) with max 4 decimal places

I want to display a human readable balance with less decimal places like metamask does it. The function formatEther(wei) returns a string, so for proper rounding I need to parse it etc. And I wanted to ask if there is an easier method or best practice how it's done.

As you said

``````const {utils, BigNumber} = require('ethers');
const balance = BigNumber.from('824213281784279560');
console.log(utils.formatEther(balance));
``````

gives `0.82421328178427956` as string.

You can

## Use BigNumber -> string (with truncation)

``````const remainder = balance.mod(1e14);
console.log(utils.formatEther(balance.sub(remainder)));
``````

gives `0.8242` as string.

## Use BigNumber -> string -> number -> string (with truncation)

``````let res = utils.formatEther(balance);
res = (+res).toFixed(4);
console.log(res);
``````

gives `0.8242` as string.

## Use BigNumber -> string -> number (with rounding)

``````let res = utils.formatEther(balance);
res = Math.round(res * 1e4) / 1e4;
console.log(res);
``````

gives `0.8242` as number.

• Worth mentioning that `toFixed` may round the number up
– 0101
Nov 29, 2023 at 13:48

Here are two different ways to do it, given `str` as the string returned by function `formatEther`:

Option #1:

``````function truncate(str, maxDecimalDigits) {
if (str.includes('.')) {
const parts = str.split('.');
return parts[0] + '.' + parts[1].slice(0, maxDecimalDigits);
}
return str;
}
``````

Option #2:

``````const Decimal = require('decimal.js');

function truncate(str, maxDecimalDigits) {
const num = new Decimal(str);
return num.toFixed(maxDecimalDigits, Decimal.ROUND_DOWN);
}
``````

Though probably not critical for your application, see here for a list of rounding modes.

• Thanks but first solution does not round and second solution uses a library. I'd prefer not to use a library for this. This might be a personal preference Jun 5, 2020 at 14:50
• @CodingYourLife: You can use `Number(str)`, then do some arithmetic on this. But knowing the typical magnitude of numeric values in this eco-system, I'm afraid that `Number` will be potentially less accurate than simply truncating the string, as I have shown in the first option above. Jun 5, 2020 at 15:03

I am posting this for other people who might encounter a similar issue:

In this instance, I find it useful to use the formatUnits() method instead. It accepts two arguments which specifies the value - the second argument specifies the decimals. You find some ERC20 tokens which do not default to 18 decimals: some tokens might even use 9 or any other allowable arbitrary decimal-length.

So the above examples could be refactored as follows (with provider and address identifiers already declared):

``````const balance = await provider.getBalance(address);
console.log('balance of \${balance} --> \${ethers.utils.formatUnits(balance, 18)}`);

``````

Try it out and see if it works.

You can use `Number.prototype.toLocaleString()` function with `minimumFractionDigits` option. The result is rounded too.

``````const balance = "0.82425328178427956"
const result = parseFloat(balance).toLocaleString("en", { minimumFractionDigits: 4 })
console.log(result) // 0.8243
``````