1 | /**
|
2 | * Convert a BigNumber to a formatted string representation.
|
3 | *
|
4 | * Syntax:
|
5 | *
|
6 | * format(value)
|
7 | * format(value, options)
|
8 | * format(value, precision)
|
9 | * format(value, fn)
|
10 | *
|
11 | * Where:
|
12 | *
|
13 | * {number} value The value to be formatted
|
14 | * {Object} options An object with formatting options. Available options:
|
15 | * {string} notation
|
16 | * Number notation. Choose from:
|
17 | * 'fixed' Always use regular number notation.
|
18 | * For example '123.40' and '14000000'
|
19 | * 'exponential' Always use exponential notation.
|
20 | * For example '1.234e+2' and '1.4e+7'
|
21 | * 'auto' (default) Regular number notation for numbers
|
22 | * having an absolute value between
|
23 | * `lower` and `upper` bounds, and uses
|
24 | * exponential notation elsewhere.
|
25 | * Lower bound is included, upper bound
|
26 | * is excluded.
|
27 | * For example '123.4' and '1.4e7'.
|
28 | * {number} precision A number between 0 and 16 to round
|
29 | * the digits of the number.
|
30 | * In case of notations 'exponential',
|
31 | * 'engineering', and 'auto',
|
32 | * `precision` defines the total
|
33 | * number of significant digits returned.
|
34 | * In case of notation 'fixed',
|
35 | * `precision` defines the number of
|
36 | * significant digits after the decimal
|
37 | * point.
|
38 | * `precision` is undefined by default.
|
39 | * {number} lowerExp Exponent determining the lower boundary
|
40 | * for formatting a value with an exponent
|
41 | * when `notation='auto`.
|
42 | * Default value is `-3`.
|
43 | * {number} upperExp Exponent determining the upper boundary
|
44 | * for formatting a value with an exponent
|
45 | * when `notation='auto`.
|
46 | * Default value is `5`.
|
47 | * {Function} fn A custom formatting function. Can be used to override the
|
48 | * built-in notations. Function `fn` is called with `value` as
|
49 | * parameter and must return a string. Is useful for example to
|
50 | * format all values inside a matrix in a particular way.
|
51 | *
|
52 | * Examples:
|
53 | *
|
54 | * format(6.4) // '6.4'
|
55 | * format(1240000) // '1.24e6'
|
56 | * format(1/3) // '0.3333333333333333'
|
57 | * format(1/3, 3) // '0.333'
|
58 | * format(21385, 2) // '21000'
|
59 | * format(12e8, {notation: 'fixed'}) // returns '1200000000'
|
60 | * format(2.3, {notation: 'fixed', precision: 4}) // returns '2.3000'
|
61 | * format(52.8, {notation: 'exponential'}) // returns '5.28e+1'
|
62 | * format(12400, {notation: 'engineering'}) // returns '12.400e+3'
|
63 | *
|
64 | * @param {BigNumber} value
|
65 | * @param {Object | Function | number} [options]
|
66 | * @return {string} str The formatted value
|
67 | */
|
68 | export function format(value, options) {
|
69 | if (typeof options === 'function') {
|
70 | // handle format(value, fn)
|
71 | return options(value);
|
72 | } // handle special cases
|
73 |
|
74 |
|
75 | if (!value.isFinite()) {
|
76 | return value.isNaN() ? 'NaN' : value.gt(0) ? 'Infinity' : '-Infinity';
|
77 | } // default values for options
|
78 |
|
79 |
|
80 | var notation = 'auto';
|
81 | var precision;
|
82 |
|
83 | if (options !== undefined) {
|
84 | // determine notation from options
|
85 | if (options.notation) {
|
86 | notation = options.notation;
|
87 | } // determine precision from options
|
88 |
|
89 |
|
90 | if (typeof options === 'number') {
|
91 | precision = options;
|
92 | } else if (options.precision) {
|
93 | precision = options.precision;
|
94 | }
|
95 | } // handle the various notations
|
96 |
|
97 |
|
98 | switch (notation) {
|
99 | case 'fixed':
|
100 | return toFixed(value, precision);
|
101 |
|
102 | case 'exponential':
|
103 | return toExponential(value, precision);
|
104 |
|
105 | case 'engineering':
|
106 | return toEngineering(value, precision);
|
107 |
|
108 | case 'auto':
|
109 | {
|
110 | // determine lower and upper bound for exponential notation.
|
111 | // TODO: implement support for upper and lower to be BigNumbers themselves
|
112 | var lowerExp = options && options.lowerExp !== undefined ? options.lowerExp : -3;
|
113 | var upperExp = options && options.upperExp !== undefined ? options.upperExp : 5; // handle special case zero
|
114 |
|
115 | if (value.isZero()) return '0'; // determine whether or not to output exponential notation
|
116 |
|
117 | var str;
|
118 | var rounded = value.toSignificantDigits(precision);
|
119 | var exp = rounded.e;
|
120 |
|
121 | if (exp >= lowerExp && exp < upperExp) {
|
122 | // normal number notation
|
123 | str = rounded.toFixed();
|
124 | } else {
|
125 | // exponential notation
|
126 | str = toExponential(value, precision);
|
127 | } // remove trailing zeros after the decimal point
|
128 |
|
129 |
|
130 | return str.replace(/((\.\d*?)(0+))($|e)/, function () {
|
131 | var digits = arguments[2];
|
132 | var e = arguments[4];
|
133 | return digits !== '.' ? digits + e : e;
|
134 | });
|
135 | }
|
136 |
|
137 | default:
|
138 | throw new Error('Unknown notation "' + notation + '". ' + 'Choose "auto", "exponential", or "fixed".');
|
139 | }
|
140 | }
|
141 | /**
|
142 | * Format a BigNumber in engineering notation. Like '1.23e+6', '2.3e+0', '3.500e-3'
|
143 | * @param {BigNumber | string} value
|
144 | * @param {number} [precision] Optional number of significant figures to return.
|
145 | */
|
146 |
|
147 | export function toEngineering(value, precision) {
|
148 | // find nearest lower multiple of 3 for exponent
|
149 | var e = value.e;
|
150 | var newExp = e % 3 === 0 ? e : e < 0 ? e - 3 - e % 3 : e - e % 3; // find difference in exponents, and calculate the value without exponent
|
151 |
|
152 | var valueWithoutExp = value.mul(Math.pow(10, -newExp));
|
153 | var valueStr = valueWithoutExp.toPrecision(precision);
|
154 |
|
155 | if (valueStr.indexOf('e') !== -1) {
|
156 | valueStr = valueWithoutExp.toString();
|
157 | }
|
158 |
|
159 | return valueStr + 'e' + (e >= 0 ? '+' : '') + newExp.toString();
|
160 | }
|
161 | /**
|
162 | * Format a number in exponential notation. Like '1.23e+5', '2.3e+0', '3.500e-3'
|
163 | * @param {BigNumber} value
|
164 | * @param {number} [precision] Number of digits in formatted output.
|
165 | * If not provided, the maximum available digits
|
166 | * is used.
|
167 | * @returns {string} str
|
168 | */
|
169 |
|
170 | export function toExponential(value, precision) {
|
171 | if (precision !== undefined) {
|
172 | return value.toExponential(precision - 1); // Note the offset of one
|
173 | } else {
|
174 | return value.toExponential();
|
175 | }
|
176 | }
|
177 | /**
|
178 | * Format a number with fixed notation.
|
179 | * @param {BigNumber} value
|
180 | * @param {number} [precision=undefined] Optional number of decimals after the
|
181 | * decimal point. Undefined by default.
|
182 | */
|
183 |
|
184 | export function toFixed(value, precision) {
|
185 | return value.toFixed(precision);
|
186 | } |
\ | No newline at end of file |