Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

Commit

Permalink
refact(formatNumber): optimisations
Browse files Browse the repository at this point in the history
  • Loading branch information
petebacondarwin committed Dec 1, 2015
1 parent 91a8b9f commit 94dc8ee
Showing 1 changed file with 47 additions and 40 deletions.
87 changes: 47 additions & 40 deletions src/ng/filter/filters.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
'use strict';

var MAX_DIGITS = 22;
var DECIMAL_SEP = '.';
var ZERO_CHAR = '0';

/**
* @ngdoc filter
* @name currency
Expand Down Expand Up @@ -137,10 +141,16 @@ function numberFilter($locale) {
};
}

var MAX_DIGITS = 22;
var DECIMAL_SEP = '.';
var ZERO_CHAR = '0';

/**
* parse a number (as a string) into three components that can be used
* for formatting the number
* @param {string} numStr The number to parse
* @return {object} An object describing this number, containing the following keys:
* - d : an array of digits containing leading zeros as necessary
* - i : the number of the digits in `d` that are to the left of the decimal point
* - e : the exponent for numbers that would need more than `MAX_DIGITS` digits in `d`
*
*/
function parse(numStr) {
var exponent = 0, digits, integerLen;
var e, i, j, zeros;
Expand Down Expand Up @@ -184,47 +194,48 @@ function parse(numStr) {
integerLen = 1;
}

return { digits: digits, exponent: exponent, integerLen: integerLen };
return { d: digits, e: exponent, i: integerLen };
}

/**
* Round the parsed number to the specified number of decimal places
* This function changed the parsedNumber in-place
*/
function roundNumber(parsedNumber, fractionSize, minFrac, maxFrac) {
var digit = 0;
var digits = parsedNumber.digits;
var fractionLen = digits.length - parsedNumber.integerLen;
var digits = parsedNumber.d;
var fractionLen = digits.length - parsedNumber.i;

// determine fractionSize if it is not specified
if (isUndefined(fractionSize)) {
fractionSize = Math.min(Math.max(minFrac, fractionLen), maxFrac);
}
// determine fractionSize if it is not specified; `+fractionSize` converts it to a number
fractionSize = (isUndefined(fractionSize)) ? Math.min(Math.max(minFrac, fractionLen), maxFrac) : +fractionSize;

// Cut off unwanted digits with rounding
for (; fractionLen > fractionSize && digits.length; fractionLen--) {
digit = digits.pop();
// Round up if necessary
if (digit >= 5) digits[digits.length - 1]++;
}
// The indec of the digit to where rounding is to occur
var roundAt = fractionSize + parsedNumber.i;
var digit = digits[roundAt];

if (!digits.length) {
if (roundAt > 0 ) {
digits.splice(roundAt);
} else {
// We rounded to zero so reset the parsedNumber
parsedNumber.integerLen = 1;
// If the last removed digit was >= 5 then we need to round up
if (digit >= 5) digits.push(1);
// Pad out with the necessary zeros
while (digits.length <= fractionSize) digits.unshift(0);
parsedNumber.i = 1;
digits.length = roundAt = fractionSize+1;
for(var i=0; i<roundAt; i++) digits[i] = 0;
}

if (digit >= 5) digits[roundAt-1]++;

// Pad out with zeros to get the required fraction length
for (; fractionLen < fractionSize; fractionLen++) digits.push(0);
for (; fractionLen < fractionSize; fractionLen++) digits.push(0);


// Do a final clear of any carrying, e.g. the last digit was rounded up to 10
// Do any carrying, e.g. a digit was rounded up to 10
var carry = digits.reduceRight(function(carry, d, i, digits) {
d = d + carry;
digits[i] = d % 10;
return Math.floor(d / 10);
}, 0);
if (carry) {
digits.unshift(carry);
parsedNumber.integerLen++;
parsedNumber.i++;
}
}

Expand All @@ -248,16 +259,11 @@ function roundNumber(parsedNumber, fractionSize, minFrac, maxFrac) {
*/
function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {

if (isObject(number)) return '';

var isNegative = number < 0;
number = Math.abs(number);

var isInfinity = number === Infinity;
if (!isInfinity && !isFinite(number)) return '';
if (!(isString(number) || isNumber(number)) || isNaN(number)) return '';

var isInfinity = !isFinite(number);
var isZero = false;
var numStr = number + '',
var numStr = Math.abs(number) + '',
formattedText = '',
parsedNumber;

Expand All @@ -268,8 +274,9 @@ function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {

roundNumber(parsedNumber, fractionSize, pattern.minFrac, pattern.maxFrac);

var digits = parsedNumber.digits;
var integerLen = parsedNumber.integerLen;
var digits = parsedNumber.d;
var integerLen = parsedNumber.i;
var exponent = parsedNumber.e;
var decimals = [];
isZero = digits.reduce(function(isZero, d) { return isZero && !d; }, true);

Expand Down Expand Up @@ -305,11 +312,11 @@ function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
formattedText += decimalSep + decimals.join('');
}

if (parsedNumber.exponent) {
formattedText += 'e+' + parsedNumber.exponent;
if (exponent) {
formattedText += 'e+' + exponent;
}
}
if (isNegative && !isZero) {
if (number < 0 && !isZero) {
return pattern.negPre + formattedText + pattern.negSuf;
} else {
return pattern.posPre + formattedText + pattern.posSuf;
Expand Down

0 comments on commit 94dc8ee

Please sign in to comment.