simple-round
Version:
A module for rounding decimals in JavaScript
204 lines (176 loc) • 6.79 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
var DIRECTIONS = {
HALF_UP: -1,
HALF_DOWN: 0,
UP: 1,
DOWN: 2
};
function fixedSimpleRound(number) {
return simpleRound(number).toFixed(2);
}
function simpleRound() {
var number = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
return round({ number: number });
}
// https://github.com/uxitten/polyfill/blob/master/string.polyfill.js
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart
if (!String.prototype.padStart) {
String.prototype.padStart = function padStart(targetLength, padString) {
targetLength = targetLength >> 0; //floor if number or convert non-number to 0;
padString = String(padString || ' ');
if (this.length > targetLength) {
return String(this);
} else {
targetLength = targetLength - this.length;
if (targetLength > padString.length) {
padString += padString.repeat(targetLength / padString.length); //append to original to ensure we are longer than needed
}
return padString.slice(0, targetLength) + String(this);
}
};
}
function fixedRound(_ref) {
var number = _ref.number,
direction = _ref.direction,
_ref$precision = _ref.precision,
precision = _ref$precision === undefined ? 2 : _ref$precision;
return round({ number: number, direction: direction, precision: precision }).toFixed(precision);
}
function round(_ref2) {
var _ref2$number = _ref2.number,
number = _ref2$number === undefined ? 0 : _ref2$number,
_ref2$direction = _ref2.direction,
direction = _ref2$direction === undefined ? DIRECTIONS.HALF_UP : _ref2$direction,
_ref2$precision = _ref2.precision,
precision = _ref2$precision === undefined ? 2 : _ref2$precision;
doValidationCheck({ number: number, direction: direction, precision: precision });
var numberString = String(number);
var sign = Math.sign(number);
numberString = numberString.indexOf('.') !== -1 ? numberString : numberString + '.';
var _numberString$split = numberString.split('.'),
_numberString$split2 = _slicedToArray(_numberString$split, 2),
originalInteger = _numberString$split2[0],
fullDecimal = _numberString$split2[1];
if (fullDecimal.length < precision + 1) {
return number;
}
var unroundedDecimal = fullDecimal.slice(0, precision + 1);
var leadingZeroes = countLeadingZeroes(unroundedDecimal);
var roundingHint = unroundedDecimal.slice(-1);
var decimalPortion = unroundedDecimal.slice(0, Math.max(precision, 1));
switch (direction) {
default:
case DIRECTIONS.HALF_UP:
{
var integerPortion = void 0;
var hintCheck = direction === DIRECTIONS.HALF_DOWN ? function (hint) {
return hint > 5;
} : function (hint) {
return hint >= 5;
};
if (hintCheck(+roundingHint)) {
var decimalNumber = void 0;
if (precision === 0) {
decimalNumber = Number(decimalPortion) + 10;
} else {
decimalNumber = Number(decimalPortion) + 1;
}
if (decimalNumber - decimalNumber % 10 > decimalPortion - decimalPortion % 10) {
var decStart = 0;
var integerNumber = void 0;
if (leadingZeroes === 0) {
integerNumber = Number(originalInteger) + sign;
decStart = 1;
} else {
integerNumber = Number(originalInteger);
leadingZeroes--;
}
decimalPortion = String(decimalNumber).slice(decStart, precision).padStart(leadingZeroes, '0');
integerPortion = String(integerNumber);
} else {
decimalPortion = String(decimalNumber);
integerPortion = String(originalInteger);
}
} else {
integerPortion = String(originalInteger);
if (precision === 0) {
decimalPortion = 0;
}
}
var result = Number(integerPortion + '.' + decimalPortion);
if (Math.sign(result) !== sign) {
return -result;
}
return result;
}
case DIRECTIONS.DOWN:
{
var power = Math.pow(10, precision);
var _sign = Math.sign(number);
return Math.floor(Math.abs(number) * power) / power * _sign;
}
case DIRECTIONS.UP:
{
var _power = Math.pow(10, precision);
var _sign2 = Math.sign(number);
return Math.ceil(Math.abs(number) * _power) / _power * _sign2;
}
}
}
function countLeadingZeroes(num) {
var i = 0;
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = num[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var n = _step.value;
if (n !== '0') {
return i;
}
i++;
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
return i;
}
function doValidationCheck(_ref3) {
var number = _ref3.number,
precision = _ref3.precision,
direction = _ref3.direction;
if (typeof number !== 'number') {
throw new Error('number must be of type Number!');
}
var contained = Object.keys(DIRECTIONS).map(function (key) {
return DIRECTIONS[key] === direction;
}).filter(function (el) {
return el === true;
});
if (!contained.length) {
throw new Error('direction must be one of UP, DOWN, HALF_UP, or HALF_DOWN');
}
if (precision < 0 || parseInt(precision) !== precision) {
throw new Error('precision must be an integer 0 or greater');
}
}
exports.round = round;
exports.fixedSimpleRound = fixedSimpleRound;
exports.fixedRound = fixedRound;
exports.simpleRound = simpleRound;
exports.DIRECTIONS = DIRECTIONS;