You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
100 lines
3.0 KiB
100 lines
3.0 KiB
'use strict'; |
|
var $ = require('../internals/export'); |
|
var global = require('../internals/global'); |
|
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 = global.RangeError; |
|
var String = global.String; |
|
var isFinite = global.isFinite; |
|
var abs = Math.abs; |
|
var floor = Math.floor; |
|
var pow = Math.pow; |
|
var round = Math.round; |
|
var un$ToExponential = uncurryThis(1.0.toExponential); |
|
var repeat = uncurryThis($repeat); |
|
var stringSlice = uncurryThis(''.slice); |
|
|
|
// Edge 17- |
|
var ROUNDS_PROPERLY = un$ToExponential(-6.9e-11, 4) === '-6.9000e-11' |
|
// IE11- && Edge 14- |
|
&& un$ToExponential(1.255, 2) === '1.25e+0' |
|
// FF86-, V8 ~ Chrome 49-50 |
|
&& un$ToExponential(12345, 3) === '1.235e+4' |
|
// FF86-, V8 ~ Chrome 49-50 |
|
&& un$ToExponential(25, 0) === '3e+1'; |
|
|
|
// IE8- |
|
var THROWS_ON_INFINITY_FRACTION = fails(function () { |
|
un$ToExponential(1, Infinity); |
|
}) && fails(function () { |
|
un$ToExponential(1, -Infinity); |
|
}); |
|
|
|
// Safari <11 && FF <50 |
|
var PROPER_NON_FINITE_THIS_CHECK = !fails(function () { |
|
un$ToExponential(Infinity, Infinity); |
|
}) && !fails(function () { |
|
un$ToExponential(NaN, Infinity); |
|
}); |
|
|
|
var FORCED = !ROUNDS_PROPERLY || !THROWS_ON_INFINITY_FRACTION || !PROPER_NON_FINITE_THIS_CHECK; |
|
|
|
// `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 un$ToExponential(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 RangeError('Incorrect fraction digits'); |
|
if (ROUNDS_PROPERLY) return un$ToExponential(x, f); |
|
var s = ''; |
|
var m = ''; |
|
var e = 0; |
|
var c = ''; |
|
var d = ''; |
|
if (x < 0) { |
|
s = '-'; |
|
x = -x; |
|
} |
|
if (x === 0) { |
|
e = 0; |
|
m = repeat('0', f + 1); |
|
} else { |
|
// this block is based on https://gist.github.com/SheetJSDev/1100ad56b9f856c95299ed0e068eea08 |
|
// TODO: improve accuracy with big fraction digits |
|
var l = log10(x); |
|
e = floor(l); |
|
var n = 0; |
|
var w = pow(10, e - f); |
|
n = round(x / w); |
|
if (2 * x >= (2 * n + 1) * w) { |
|
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; |
|
} |
|
});
|
|
|