UNPKG

core-js

Version:
108 lines (100 loc) 3.31 kB
'use strict'; var $ = require('../internals/export'); var uncurryThis = require('../internals/function-uncurry-this'); var toIntegerOrInfinity = require('../internals/to-integer-or-infinity'); var thisNumberValue = require('../internals/this-number-value'); var $repeat = require('../internals/string-repeat'); var log10 = require('../internals/math-log10'); var fails = require('../internals/fails'); var $RangeError = RangeError; var $String = String; var $isFinite = isFinite; var abs = Math.abs; var floor = Math.floor; var pow = Math.pow; var round = Math.round; var nativeToExponential = uncurryThis(1.1.toExponential); var repeat = uncurryThis($repeat); var stringSlice = uncurryThis(''.slice); var POW_10_308 = pow(10, 308); // Edge 17- var ROUNDS_PROPERLY = nativeToExponential(-6.9e-11, 4) === '-6.9000e-11' // IE11- && Edge 14- && nativeToExponential(1.255, 2) === '1.25e+0' // FF86-, V8 ~ Chrome 49-50 && nativeToExponential(12345, 3) === '1.235e+4' // FF86-, V8 ~ Chrome 49-50 && nativeToExponential(25, 0) === '3e+1'; // IE8- var throwsOnInfinityFraction = function () { return fails(function () { nativeToExponential(1, Infinity); }) && fails(function () { nativeToExponential(1, -Infinity); }); }; // Safari <11 && FF <50 var properNonFiniteThisCheck = function () { return !fails(function () { nativeToExponential(Infinity, Infinity); nativeToExponential(NaN, Infinity); }); }; var FORCED = !ROUNDS_PROPERLY || !throwsOnInfinityFraction() || !properNonFiniteThisCheck(); // `Number.prototype.toExponential` method // https://tc39.es/ecma262/#sec-number.prototype.toexponential $({ target: 'Number', proto: true, forced: FORCED }, { toExponential: function toExponential(fractionDigits) { var x = thisNumberValue(this); if (fractionDigits === undefined) return nativeToExponential(x); var f = toIntegerOrInfinity(fractionDigits); if (!$isFinite(x)) return String(x); // TODO: ES2018 increased the maximum number of fraction digits to 100, need to improve the implementation if (f < 0 || f > 20) throw new $RangeError('Incorrect fraction digits'); if (ROUNDS_PROPERLY) return nativeToExponential(x, f); var s = ''; var m, e, c, d, l, n, xScaled; if (x < 0) { s = '-'; x = -x; } if (x === 0) { e = 0; m = repeat('0', f + 1); } else { // TODO: improve accuracy with big fraction digits l = log10(x); e = floor(l); // compute x / pow(10, e - f) and round, avoiding underflow/overflow if (f - e >= 308) { // pow(10, e - f) would underflow to a subnormal or zero; split computation xScaled = x * POW_10_308 * pow(10, f - e - 308); } else { xScaled = x / pow(10, e - f); } n = round(xScaled); // correct tie-breaking: round half up // avoids `2 * x` overflow for values near MAX_VALUE if (xScaled - n >= 0.5) { n += 1; } if (n >= pow(10, f + 1)) { n /= 10; e += 1; } m = $String(n); } if (f !== 0) { m = stringSlice(m, 0, 1) + '.' + stringSlice(m, 1); } if (e === 0) { c = '+'; d = '0'; } else { c = e > 0 ? '+' : '-'; d = $String(abs(e)); } m += 'e' + c + d; return s + m; } });