From c8b818f011257b09f98d12fabde92ba5a77a43d3 Mon Sep 17 00:00:00 2001 From: jdalton Date: Sun, 7 Jun 2015 21:27:00 -0700 Subject: [PATCH] Cleanup `_.ceil`, `_.floor`, & `_.round`. --- lodash.src.js | 201 +++++++++++++++++++++++++------------------------- test/test.js | 18 +++-- 2 files changed, 111 insertions(+), 108 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 80c556e07..559281f28 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -749,10 +749,9 @@ /** Native method references. */ var ArrayBuffer = context.ArrayBuffer, - ceil = Math.ceil, clearTimeout = context.clearTimeout, - floor = Math.floor, parseFloat = context.parseFloat, + pow = Math.pow, propertyIsEnumerable = objectProto.propertyIsEnumerable, Set = getNative(context, 'Set'), setTimeout = context.setTimeout, @@ -761,7 +760,9 @@ WeakMap = getNative(context, 'WeakMap'); /* Native method references for those with the same name as other `lodash` methods. */ - var nativeCreate = getNative(Object, 'create'), + var nativeCeil = Math.ceil, + nativeCreate = getNative(Object, 'create'), + nativeFloor = Math.floor, nativeIsArray = getNative(Array, 'isArray'), nativeIsFinite = context.isFinite, nativeKeys = getNative(Object, 'keys'), @@ -2608,7 +2609,7 @@ * @returns {number} Returns the random number. */ function baseRandom(min, max) { - return min + floor(nativeRandom() * (max - min + 1)); + return min + nativeFloor(nativeRandom() * (max - min + 1)); } /** @@ -2933,7 +2934,7 @@ valIsUndef = value === undefined; while (low < high) { - var mid = floor((low + high) / 2), + var mid = nativeFloor((low + high) / 2), computed = iteratee(array[mid]), isDef = computed !== undefined, isReflexive = computed === computed; @@ -3650,7 +3651,7 @@ } var padLength = length - strLength; chars = chars == null ? ' ' : (chars + ''); - return repeat(chars, ceil(padLength / chars.length)).slice(0, padLength); + return repeat(chars, nativeCeil(padLength / chars.length)).slice(0, padLength); } /** @@ -3690,6 +3691,25 @@ return wrapper; } + /** + * Creates a `_.ceil`, `_.floor`, or `_.round` function. + * + * @private + * @param {string} methodName The name of the `Math` method to use when rounding. + * @returns {Function} Returns the new round function. + */ + function createRound(methodName) { + var func = Math[methodName]; + return function(number, precision) { + precision = precision === undefined ? 0 : (+precision || 0); + if (precision) { + precision = pow(10, precision); + return func(number * precision) / precision; + } + return func(number); + }; + } + /** * Creates a `_.sortedIndex` or `_.sortedLastIndex` function. * @@ -3706,25 +3726,6 @@ }; } - /** - * Creates a `_.round`, `_.ceil`, or `_.floor` function. - * - * @private - * @param {String} type Specify the Math method to use when rounding. - */ - - function createRound(type) { - var roundFn = Math[type]; - return function(number, precision) { - if (precision) { - precision = Math.pow(10, precision); - return roundFn(number * precision) / precision; - } else { - return roundFn(number); - } - } - } - /** * Creates a function that either curries or invokes `func` with optional * `this` binding and partially applied arguments. @@ -4572,12 +4573,12 @@ if (guard ? isIterateeCall(array, size, guard) : size == null) { size = 1; } else { - size = nativeMax(floor(size) || 1, 1); + size = nativeMax(nativeFloor(size) || 1, 1); } var index = 0, length = array ? array.length : 0, resIndex = -1, - result = Array(ceil(length / size)); + result = Array(nativeCeil(length / size)); while (index < length) { result[++resIndex] = baseSlice(array, index, (index += size)); @@ -10260,7 +10261,7 @@ */ function inRange(value, start, end) { start = +start || 0; - if (typeof end === 'undefined') { + if (end === undefined) { end = start; start = 0; } else { @@ -10543,8 +10544,8 @@ return string; } var mid = (length - strLength) / 2, - leftLength = floor(mid), - rightLength = ceil(mid); + leftLength = nativeFloor(mid), + rightLength = nativeCeil(mid); chars = createPadding('', rightLength, chars); return chars.slice(0, leftLength) + string + chars; @@ -10667,7 +10668,7 @@ if (n % 2) { result += string; } - n = floor(n / 2); + n = nativeFloor(n / 2); string += string; } while (n); @@ -11644,7 +11645,7 @@ // Use `Array(length)` so engines like Chakra and V8 avoid slower modes. // See https://youtu.be/XAqIpGU8ZZk#t=17m25s for more details. var index = -1, - length = nativeMax(ceil((end - start) / (step || 1)), 0), + length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), result = Array(length); while (++index < length) { @@ -11682,7 +11683,7 @@ * // => also invokes `mage.castSpell(n)` three times */ function times(n, iteratee, thisArg) { - n = floor(n); + n = nativeFloor(n); // Exit early to avoid a JSC JIT bug in Safari 8 // where `Array(0)` is treated as `Array(1)`. @@ -11744,6 +11745,50 @@ return (+augend || 0) + (+addend || 0); } + /** + * Calculates `n` rounded up to `precision`. + * + * @static + * @memberOf _ + * @category Math + * @param {number} n The number to round up. + * @param {number} [precision=0] The precision to round up to. + * @returns {number} Returns the rounded up number. + * @example + * + * _.ceil(4.006); + * // => 5 + * + * _.ceil(6.004, 2); + * // => 6.01 + * + * _.ceil(6040, -2); + * // => 6100 + */ + var ceil = createRound('ceil'); + + /** + * Calculates `n` rounded down to `precision`. + * + * @static + * @memberOf _ + * @category Math + * @param {number} n The number to round down. + * @param {number} [precision=0] The precision to round down to. + * @returns {number} Returns the rounded down number. + * @example + * + * _.floor(4.006); + * // => 4 + * + * _.floor(0.046, 2); + * // => 0.04 + * + * _.floor(4060, -2); + * // => 4000 + */ + var floor = createRound('floor'); + /** * Gets the maximum value of `collection`. If `collection` is empty or falsey * `-Infinity` is returned. If an iteratee function is provided it is invoked @@ -11842,6 +11887,28 @@ */ var min = createExtremum(lt, POSITIVE_INFINITY); + /** + * Calculates `n` rounded to `precision`. + * + * @static + * @memberOf _ + * @category Math + * @param {number} n The number to round. + * @param {number} [precision=0] The precision to round to. + * @returns {number} Returns the rounded number. + * @example + * + * _.round(4.006); + * // => 4 + * + * _.round(4.006, 2); + * // => 4.01 + * + * _.round(4060, -2); + * // => 4100 + */ + var round = createRound('round'); + /** * Gets the sum of the values in `collection`. * @@ -11890,72 +11957,6 @@ : baseSum(collection, iteratee); } - /** - * Calculates the result of a number rounded to an optional precision. - * - * @static - * @memberOf _ - * @category Math - * @param {number} number The number to round. - * @param {number} [precision] The precision to round to. - * @returns {number} Returns the rounded number. - * @example - * - * _.round(4.006); - * // => 4 - * - * _.round(4.006, 2); - * // => 4.01 - * - * _.round(4060, -2); - * // => 4100 - */ - var round = createRound('round'); - - /** - * Calculates the result of a number rounded down to an optional precision. - * - * @static - * @memberOf _ - * @category Math - * @param {number} number The number to round down. - * @param {number} [precision] The precision to round down to. - * @returns {number} Returns the rounded down number. - * @example - * - * _.floor(4.006); - * // => 4 - * - * _.floor(0.046, 2); - * // => 0.04 - * - * _.floor(4060, -2); - * // => 4000 - */ - var floor = createRound('floor'); - - /** - * Calculates the result of a number rounded up to an optional precision. - * - * @static - * @memberOf _ - * @category Math - * @param {number} number The number to round up. - * @param {number} [precision] The precision to round up to. - * @returns {number} Returns the rounded up number. - * @example - * - * _.ceil(4.006); - * // => 5 - * - * _.ceil(6.004, 2); - * // => 6.01 - * - * _.ceil(6040, -2); - * // => 6100 - */ - var ceil = createRound('ceil'); - /*------------------------------------------------------------------------*/ // Ensure wrappers are instances of `baseLodash`. @@ -12256,7 +12257,7 @@ if (filtered && !index) { return new LazyWrapper(this); } - n = n == null ? 1 : nativeMax(floor(n) || 0, 0); + n = n == null ? 1 : nativeMax(nativeFloor(n) || 0, 0); var result = this.clone(); if (filtered) { diff --git a/test/test.js b/test/test.js index 869a0ce9d..eb59453cb 100644 --- a/test/test.js +++ b/test/test.js @@ -13686,29 +13686,31 @@ /*--------------------------------------------------------------------------*/ - QUnit.module('lodash.round, lodash.floor, and lodash.ceil'); + QUnit.module('round methods'); - _.each(['round', 'floor', 'ceil'], function(methodName) { - var func = _[methodName]; + _.each(['ceil', 'floor', 'round'], function(methodName) { + var func = _[methodName], + isCeil = methodName == 'ceil', + isFloor = methodName == 'floor'; test('`_.' + methodName + '` should return a rounded number without a precision', 1, function() { var actual = func(4.006); - equal(actual, methodName === 'ceil' ? 5 : 4); + strictEqual(actual, isCeil ? 5 : 4); }); - test('`_.' + methodName + '` should return a rounded number with a precision of 0', 1, function() { + test('`_.' + methodName + '` should return a rounded number with a precision of `0`', 1, function() { var actual = func(4.006, 0); - equal(actual, methodName === 'ceil' ? 5 : 4); + strictEqual(actual, isCeil ? 5 : 4); }); test('`_.' + methodName + '` should return a rounded number with a positive precision', 1, function() { var actual = func(4.016, 2); - equal(actual, methodName === 'floor' ? 4.01 : 4.02); + strictEqual(actual, isFloor ? 4.01 : 4.02); }); test('`_.' + methodName + '` should return a rounded number with a negative precision', 1, function() { var actual = func(4160, -2); - equal(actual, methodName === 'floor' ? 4100 : 4200); + strictEqual(actual, isFloor ? 4100 : 4200); }); });