I was looking for a good way to format exponential values that satisfies all of the following...
<canvas>
elements10
, 2
, e
)9x10^3
The easy solution I found was to use some npm package like numeral.js
, and just do something like...
const n = 9000;
const label = numeral(n).format('0[.]00e+0') // 9e+3
Which not terrible for base 10 but when using base 2
or e
it isn't great
numeral(Math.pow(2, 4)).format('0,0e+0') // 2e+1
I ended up creating my own function that I think is a huge improvement from the numeral.js
exponential formatter.
const superscriptMap: Record<string, string> = {
0: '⁰',
1: '¹',
2: '²',
3: '³',
4: '⁴',
5: '⁵',
6: '⁶',
7: '⁷',
8: '⁸',
9: '⁹',
};
const getSuperScriptNumber = (n: number) =>
`${n > 0 ? '' : '⁻'}${Math.abs(n)
.toString()
.split('')
.map((c) => superStringMap[c])
.join('')}`;
const logFormatter = (n: number, base: number = 10) => {
// Number.EPSILON to help with rounding errors
const sign = n < 0 ? '-' : '';
const nAbs = Math.abs(n);
const exp = Math.log(nAbs) / Math.log(logBaseMap[base]) + Number.EPSILON;
const roundedExp = Math.floor(exp);
const constant = numeral(nAbs / Math.pow(logBaseMap[base], roundedExp)).format('0[.]00');
const baseLabel = base === LogBase.Natural ? 'e' : logBaseMap[base];
const expString = getSuperScriptNumber(roundedExp);
return `${sign}${constant} x ${baseLabel}${expString}`;
};
Using this function I summarized a few example formatted values below.
Base (base) | Exponent (exp) | Math.pow(base, exp) |
numeral(n).format('0[.]00e+0') |
logFormatter(n, base) |
---|---|---|---|---|
10 | -5 | 0.000009999999999999999 | 10e-6 | 1 x 10⁻⁵ |
10 | -2.445 | 0.0035892193464500534 | 3.59e-3 | 3.59 x 10⁻³ |
10 | -1 | 0.1 | 1e-1 | 1 x 10⁻¹ |
10 | 0 | 1 | 1e+0 | 1 x 10⁻⁰ |
10 | 1 | 10 | 1e+1 | 1 x 10¹ |
10 | 2.545 | 350.75187395256796 | 3.51e+2 | 3.51 x 10² |
10 | 5 | 100000 | 1e+5 | 1 x 10⁵ |
2 | -5 | 0.03125 | 3.13e-2 | 1 x 2⁻⁵ |
2 | -2.445 | 0.18364607915978864 | 1.84e-1 | 1.47 x 2⁻³ |
2 | -1 | 0.5 | 5e-1 | 1 x 2⁻¹ |
2 | 0 | 1 | 1e+0 | 1 x 2⁻⁰ |
2 | 1 | 2 | 2e+0 | 1 x 2¹ |
2 | 2.545 | 5.836081376960701 | 5.84e+0 | 1.46 x 2² |
2 | 5 | 32 | 3.20e+1 | 1 x 2⁵ |
Math.E |
-5 | 0.006737946999085469 | 6.74e-3 | 1 x e⁻⁵ |
Math.E |
-2.445 | 0.08672613490173116 | 8.67e-2 | 1.74 x e⁻³ |
Math.E |
-1 | 0.36787944117144233 | 3.68e-1 | 1 x e⁻¹ |
Math.E |
0 | 1 | 1e+0 | 1 x e⁻⁰ |
Math.E |
1 | 2.718281828459045 | 2.72e+0 | 1 x e¹ |
Math.E |
2.545 | 12.743228086065521 | 1.27e+1 | 1.72 x e² |
Math.E |
5 | 148.41315910257657 | 1.48e+2 | 1 x e⁵ |
I hope this helps someone that is in my position. Please edit this port or let me know if there is a calculation error.