to-exponential
Version:
Converts any big/small/precise decimal number represented as String, to exponential notation.
69 lines (51 loc) • 2.57 kB
JavaScript
module.exports = toExponential;
module.exports.addBigInts = addBigInts;
var numberRegEx = /^([+-])?([0-9.]+)(?:[e|E]([+-]?[0-9]+))?$/;
function toExponential(str) {
var m = str.match(numberRegEx); // Split the number into separate parts.
if (m === null) return false;
var s = m[1] === '-' ? '-' : ''; // `s`: sign part.
var n = m[2]; // `n`: number's main part: decimals, incl. `.`.
var e = m[3] || '0'; // `e`: exponent part.
if (e[0] === '+') e = e.substr(1);
var p = n.indexOf('.'); // E.g.: '00.0001230' -> 2. Position of the dot.
if (p < 0) p = n.length; // E.g.: '01230' -> 5
var u = n.replace(/\./g, ''); // E.g.: '00.0001230' -> u = '000001230'
if (!u || u.length < n.length - 1) return false; // No '.' nor '1.2.3'
var l = u.search(/[1-9]/); // Count leading zeros, e.g.: '000001230' -> 5
if (l < 0) return '0e+0'; // Case with only zeros, e.g.: '00000'
// Adjust the exponent based on the amount of dot-shift;
// e.g. for n = '00.0001230e+10' -> e = 10 + (2-1) - 5 = 6
// Note: `p` and `l` fit in a JS Number, else `n` wouldn't fit in a String.
e = addBigInts(e, (p - 1 - l).toString());
n = u.substr(l).replace(/0+$/, ''); // Trim 0s for expon. not., e.g. -> '123'
if (n.length > 1) n = n[0] + '.' + n.substr(1); // E.g. -> '1.23'
return s + n + 'e' + (e[0] != '-' ? '+' : '') + e.toString();
}
// Adds two possibly big, possibly signed integers, represented as strings.
function addBigInts(a, b) {
var sa = a[0] === '-' ? 1 : 0; // Put aside a sign. Only '-' allowed, not '+'.
var sb = b[0] === '-' ? 1 : 0;
if (sa) a = a.substr(1);
if (sb) b = b.substr(1);
var eq = sa === sb; // Equal sign => real addition, else actually subtraction.
a = a.replace(/^0+/, ''); // Remove leading zeros.
b = b.replace(/^0+/, '');
if ( (a === '' && b === '') || (!eq && a === b) ) return '0';
if ( !eq && (a.length < b.length || (a.length === b.length && a < b)) ) {
var x = a; a = b; b = x; // For subtraction, swap to make a > b; ..
sa = sb; // ..then e.g.: `-6 + 2 = - (6 - 2)`, and `6 + -2 = (6 - 2)`.
}
// Merged code for addition/subtraction of two positive integers that are
// represented as strings.
a = a.split('');
b = b.split('');
var carry = 0;
var acc = '';
while (a.length || b.length || carry) {
carry = ~~a.pop() + (eq ? ~~b.pop() + carry: -~~b.pop() - carry);
acc = (carry + 10) % 10 + acc;
carry = eq ? carry > 9 : carry < 0;
}
return (sa ? '-' : '') + acc.replace(/^0+/, '');
}