指数数格式化程序 - javascript
Exponential number formatter - javascript
我一直在寻找一种格式化满足以下所有条件的指数值的好方法...
- 适用于 HTML
<canvas>
个元素
- 具有可配置的基值(即
10
、2
、e
)
- 将指数显示为上标,而不仅仅是
9x10^3
- 处理负上标指数
我找到的简单解决方案是使用一些像 numeral.js
这样的 npm 包,然后做一些像...
const n = 9000;
const label = numeral(n).format('0[.]00e+0') // 9e+3
这对于以 10 为基数的来说并不可怕,但是当使用以 2
或 e
为基数时,它并不好
numeral(Math.pow(2, 4)).format('0,0e+0') // 2e+1
我最终创建了自己的函数,我认为这是对 numeral.js
指数格式化程序的巨大改进。
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}`;
};
使用此函数,我在下面总结了一些示例格式化值。
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.
我一直在寻找一种格式化满足以下所有条件的指数值的好方法...
- 适用于 HTML
<canvas>
个元素 - 具有可配置的基值(即
10
、2
、e
) - 将指数显示为上标,而不仅仅是
9x10^3
- 处理负上标指数
我找到的简单解决方案是使用一些像 numeral.js
这样的 npm 包,然后做一些像...
const n = 9000;
const label = numeral(n).format('0[.]00e+0') // 9e+3
这对于以 10 为基数的来说并不可怕,但是当使用以 2
或 e
为基数时,它并不好
numeral(Math.pow(2, 4)).format('0,0e+0') // 2e+1
我最终创建了自己的函数,我认为这是对 numeral.js
指数格式化程序的巨大改进。
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}`;
};
使用此函数,我在下面总结了一些示例格式化值。
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.