1 | 'use strict';
|
---|
2 | var $ = require('../internals/export');
|
---|
3 | var uncurryThis = require('../internals/function-uncurry-this');
|
---|
4 | var toIntegerOrInfinity = require('../internals/to-integer-or-infinity');
|
---|
5 | var thisNumberValue = require('../internals/this-number-value');
|
---|
6 | var $repeat = require('../internals/string-repeat');
|
---|
7 | var log10 = require('../internals/math-log10');
|
---|
8 | var fails = require('../internals/fails');
|
---|
9 |
|
---|
10 | var $RangeError = RangeError;
|
---|
11 | var $String = String;
|
---|
12 | var $isFinite = isFinite;
|
---|
13 | var abs = Math.abs;
|
---|
14 | var floor = Math.floor;
|
---|
15 | var pow = Math.pow;
|
---|
16 | var round = Math.round;
|
---|
17 | var nativeToExponential = uncurryThis(1.0.toExponential);
|
---|
18 | var repeat = uncurryThis($repeat);
|
---|
19 | var stringSlice = uncurryThis(''.slice);
|
---|
20 |
|
---|
21 | // Edge 17-
|
---|
22 | var ROUNDS_PROPERLY = nativeToExponential(-6.9e-11, 4) === '-6.9000e-11'
|
---|
23 | // IE11- && Edge 14-
|
---|
24 | && nativeToExponential(1.255, 2) === '1.25e+0'
|
---|
25 | // FF86-, V8 ~ Chrome 49-50
|
---|
26 | && nativeToExponential(12345, 3) === '1.235e+4'
|
---|
27 | // FF86-, V8 ~ Chrome 49-50
|
---|
28 | && nativeToExponential(25, 0) === '3e+1';
|
---|
29 |
|
---|
30 | // IE8-
|
---|
31 | var throwsOnInfinityFraction = function () {
|
---|
32 | return fails(function () {
|
---|
33 | nativeToExponential(1, Infinity);
|
---|
34 | }) && fails(function () {
|
---|
35 | nativeToExponential(1, -Infinity);
|
---|
36 | });
|
---|
37 | };
|
---|
38 |
|
---|
39 | // Safari <11 && FF <50
|
---|
40 | var properNonFiniteThisCheck = function () {
|
---|
41 | return !fails(function () {
|
---|
42 | nativeToExponential(Infinity, Infinity);
|
---|
43 | nativeToExponential(NaN, Infinity);
|
---|
44 | });
|
---|
45 | };
|
---|
46 |
|
---|
47 | var FORCED = !ROUNDS_PROPERLY || !throwsOnInfinityFraction() || !properNonFiniteThisCheck();
|
---|
48 |
|
---|
49 | // `Number.prototype.toExponential` method
|
---|
50 | // https://tc39.es/ecma262/#sec-number.prototype.toexponential
|
---|
51 | $({ target: 'Number', proto: true, forced: FORCED }, {
|
---|
52 | toExponential: function toExponential(fractionDigits) {
|
---|
53 | var x = thisNumberValue(this);
|
---|
54 | if (fractionDigits === undefined) return nativeToExponential(x);
|
---|
55 | var f = toIntegerOrInfinity(fractionDigits);
|
---|
56 | if (!$isFinite(x)) return String(x);
|
---|
57 | // TODO: ES2018 increased the maximum number of fraction digits to 100, need to improve the implementation
|
---|
58 | if (f < 0 || f > 20) throw new $RangeError('Incorrect fraction digits');
|
---|
59 | if (ROUNDS_PROPERLY) return nativeToExponential(x, f);
|
---|
60 | var s = '';
|
---|
61 | var m, e, c, d;
|
---|
62 | if (x < 0) {
|
---|
63 | s = '-';
|
---|
64 | x = -x;
|
---|
65 | }
|
---|
66 | if (x === 0) {
|
---|
67 | e = 0;
|
---|
68 | m = repeat('0', f + 1);
|
---|
69 | } else {
|
---|
70 | // this block is based on https://gist.github.com/SheetJSDev/1100ad56b9f856c95299ed0e068eea08
|
---|
71 | // TODO: improve accuracy with big fraction digits
|
---|
72 | var l = log10(x);
|
---|
73 | e = floor(l);
|
---|
74 | var w = pow(10, e - f);
|
---|
75 | var n = round(x / w);
|
---|
76 | if (2 * x >= (2 * n + 1) * w) {
|
---|
77 | n += 1;
|
---|
78 | }
|
---|
79 | if (n >= pow(10, f + 1)) {
|
---|
80 | n /= 10;
|
---|
81 | e += 1;
|
---|
82 | }
|
---|
83 | m = $String(n);
|
---|
84 | }
|
---|
85 | if (f !== 0) {
|
---|
86 | m = stringSlice(m, 0, 1) + '.' + stringSlice(m, 1);
|
---|
87 | }
|
---|
88 | if (e === 0) {
|
---|
89 | c = '+';
|
---|
90 | d = '0';
|
---|
91 | } else {
|
---|
92 | c = e > 0 ? '+' : '-';
|
---|
93 | d = $String(abs(e));
|
---|
94 | }
|
---|
95 | m += 'e' + c + d;
|
---|
96 | return s + m;
|
---|
97 | }
|
---|
98 | });
|
---|