How can i reduce the time of execution of this code - javascript

var yourself = {
fibonacci : function(n) {
return n === 0 ? 0 : n === 1 ? 1 :
this.fibonacci(n -1) + this.fibonacci (n-2)
}
};
This function is constantly setting the value of its 'fibonacci' property based on the
arguement supplied for 'n' parameter of the function.
I would like to refactor the function to reduce execution time

Using dynamic programming, Memoization that cache the already calculated result
read more about memoization here
const memoFib = function () {
let memo = {}
return function fib(n) {
if (n in memo) { return memo[n] }
else {
if (n <= 1) { memo[n] = n }
else { memo[n] = fib(n - 1) + fib(n - 2) }
return memo[n]
}
}
}
const fib = memoFib()
console.log(fib(50));

You could implement some kind of caching. This way you don't need to recalculate the same result multiple times.
var yourself = {
fibonacci : function(n, cache = new Map()) {
if(cache.has(n)) return cache.get(n);
if(n === 0) return 0;
if(n === 1) return 1;
const start = this.fibonacci(n-1, cache);
const end = this.fibonacci(n-2, cache);
cache.set(n-1, start);
cache.set(n-2, end);
return start + end;
}
};
console.log(yourself.fibonacci(40));

Related

Binary Search for multiple items within a Range (Log time filter)

I have an Array of Log items, already sorted by their timestamp (number of milliseconds since 1970). Now I want to filter them by a specific time range, so I think of Binary Search, however this variant is different than all variants I knew before as I need to find a range within a range. Note that there may be none or multiple items at the value edges.
I came up with this to reduce one range requirement but still don't know how to get to the first/last edge items:
filterByTime(min: number, max: number): LogItem[] {
const items = this.items;
const len = items.length;
if (min === undefined && max === undefined) {
return items.slice(0, len - 1);
}
min = min || Number.MIN_VALUE;
max = max || Number.MAX_VALUE;
const fn = (a: LogItem) => {
if (a.time < min) {
return -1;
} else if (a.time > max) {
return 1;
} else {
return 0;
}
};
const lowerBound = this.binarySearchBound(fn, 0, len, true);
if (lowerBound == -1) { return []; }
const upperBound = this.binarySearchBound(fn, 0, len, false);
return items.slice(lowerBound, upperBound + 1);
}
binarySearchBound(compareFn: (a: LogItem) => number, left: number, right: number, isLowerBound: boolean): number {
const items = this.items;
if (items.length == 0) {
return -1;
}
if (isLowerBound && compareFn(items[0]) == 0) {
return 0;
} else if (!isLowerBound && compareFn(items[items.length - 1]) == 0) {
return items.length - 1;
}
while (left <= right) {
const mid = (left + right) / 2;
const item = this.items[mid];
const compare = compareFn(item);
if (compare < 0) {
left = mid + 1;
} else if (compare > 0) {
right = mid - 1;
} else {
// What to do now?
}
}
return -1;
}
Worst case scenario, I can just do a linear search from the edge since I can assume there are not that much items at the edge but surely there is a better way I didn't think of but then I may have to iterate through the whole result set if mid falls in the middle of the result set.
EDIT for adding a note: It's possible for min or max is undefined (and could be both, in which case I can just set an if and return the copy of the whole array). Is it better to just substitute it with MIN_VALUE and MAX_VALUE if they are undefined, or is there a better way to handle that case?
I would suggest the following:
Write two binary search functions, as the execution time is then not hampered by passing and checking the isLowerBound boolean.
Make the returned upperBound to mean the next index after the potential last index that belongs to the range. This corresponds with how arguments work with native functions like slice.
Don't use -1 as a special index. If coded well, an empty range will come out of the two binary searches any way and give an empty array as result
Make the compare function to work with 2 parameters, so you can actually search for either the min or the max value.
Yes, I would use MIN_VALUE and MAX_VALUE as defaults and not test for boundary cases. If boundary cases happen often, it might be worth to include those checks, but in general be aware that these checks will then be executed for every filter, which may bring down the average execution time.
Here is the suggested implementation with integer data (instead of objects) to keep it simple. In order to have it run in a snippet I also removed the type references:
function filterByTime(min=Number.MIN_VALUE, max=Number.MAX_VALUE) {
const fn = (a, b) => a - b; // simplified (should be a.time - b.time)
const lowerBound = this.binarySearchLowerBound(fn, 0, this.items.length, min);
const upperBound = this.binarySearchUpperBound(fn, lowerBound, this.items.length, max);
return this.items.slice(lowerBound, upperBound);
}
function binarySearchLowerBound(compareFn, left, right, target) {
while (left < right) {
const mid = (left + right) >> 1;
if (compareFn(this.items[mid], target) < 0) {
left = mid + 1;
} else { // Also when equal...
right = mid;
}
}
return left;
}
function binarySearchUpperBound(compareFn, left, right, target) {
while (left < right) {
const mid = (left + right) >> 1;
if (compareFn(this.items[mid], target) <= 0) { // Also when equal...
left = mid + 1;
} else {
right = mid;
}
}
return left;
}
// Demo with simplified data (instead of objects with time property)
this.items = [1, 2, 2, 2, 3, 4, 4, 5, 5, 5, 6, 7, 8, 8];
console.log(this.filterByTime(2, 4));
console.log(this.filterByTime(4, 5));
Combined the variants on this article, I merged first and last code into a single function:
filterByTime(items: LogItem[], min: number, max: number): LogItem[] {
const len = items.length;
if (len == 0) {
return [];
}
if (min === undefined && max === undefined) {
return items.slice(0, len - 1);
}
min = min || Number.MIN_VALUE;
max = max || Number.MAX_VALUE;
const fn = (a: LogItem) => {
if (a.time < min) {
return -1;
} else if (a.time > max) {
return 1;
} else {
return 0;
}
};
const lowerBound = this.binarySearchBound(fn, 0, len, true);
if (lowerBound == -1) { return []; }
const upperBound = this.binarySearchBound(fn, 0, len, false);
return items.slice(lowerBound, upperBound + 1);
}
binarySearchBound(compareFn: (a: LogItem) => number, left: number, right: number, isLowerBound: boolean): number {
const items = this.items;
if (items.length == 0) {
return -1;
}
if (isLowerBound && compareFn(items[0]) == 0) {
return 0;
} else if (!isLowerBound && compareFn(items[items.length - 1]) == 0) {
return items.length - 1;
}
let result = -1;
while (left <= right) {
const mid = (left + right) / 2;
const item = this.items[mid];
const compare = compareFn(item);
if (compare < 0) {
left = mid + 1;
} else if (compare > 0) {
right = mid - 1;
} else {
result = mid;
if (isLowerBound) {
right = mid - 1;
} else {
left = mid + 1;
}
}
}
return result;
}

How to generate a random number based on fixed character set in javascript

I'm generating a number based on a fixed character set.
function generator()
{
var text = "";
var char_list = "LEDGJR", number_list = "0123456789";
for(var i=0; i < 2; i++ )
{
text += char_list.charAt(Math.floor(Math.random() * char_list.length));
}
for(var j=0; j < 2; j++ )
{
text += number_list.charAt(Math.floor(Math.random() *
number_list.length));
}
return text;
}
Result :
RE39, JE12 etc...
Once all the permutation related to the above sequence is done, then the generator should generate string as RE391, JE125 means adding one more number to the complete number.
How can I get the permutation count of sequence?
For simplicity consider the case where:
chars = "AB"
nums = "123";
and we want to generate a 4-digit sequence of two chars and two numbers.
We define these variables
rows = [chars, chars, nums, nums]
rowSizes = rows.map(row => row.length) // [2, 2, 3, 3]
It’s easy to see the set size of all possible permuations equals:
spaceSize = rowSizes.reduce((m, n) => m * n, 1) // 2*2*3*3 = 36
And we define two set of utility functions, usage of which I'll explain in detail later.
decodeIndex() which gives us uniqueness
function euclideanDivision(a, b) {
const remainder = a % b;
const quotient = (a - remainder) / b;
return [quotient, remainder]
}
function decodeIndex(index, rowSizes) {
const rowIndexes = []
let dividend = index
for (let i = 0; i < rowSizes.length; i++) {
const [quotient, remainder] = euclideanDivision(dividend, rowSizes[i])
rowIndexes[i] = remainder
dividend = quotient
}
return rowIndexes
}
getNextIndex() which gives us pseudo-randomness
function isPrime(n) {
if (n <= 1) return false;
if (n <= 3) return true;
if (n % 2 == 0 || n % 3 == 0) return false;
for (let i = 5; i * i <= n; i = i + 6) {
if (n % i == 0 || n % (i + 2) == 0) return false;
}
return true;
}
function findNextPrime(n) {
if (n <= 1) return 2;
let prime = n;
while (true) {
prime++;
if (isPrime(prime)) return prime;
}
}
function getIndexGeneratorParams(spaceSize) {
const N = spaceSize;
const Q = findNextPrime(Math.floor(2 * N / (1 + Math.sqrt(5))))
const firstIndex = Math.floor(Math.random() * spaceSize);
return [firstIndex, N, Q]
}
function getNextIndex(prevIndex, N, Q) {
return (prevIndex + Q) % N
}
Uniqueness
Like mentioned above, spaceSize is the number of all possible permutations, thus each index in range(0, spaceSize) uniquely maps to one permutation. decodeIndex helps with this mapping, you can get the corresponding permutation to an index by:
function getSequenceAtIndex(index) {
const tuple = decodeIndex(index, rowSizes)
return rows.map((row, i) => row[tuple[i]]).join('')
}
Pseudo-Randomness
(Credit to this question. I just port that code into JS.)
We get pseudo-randomness by polling a "full cycle iterator"†. The idea is simple:
have the indexes 0..35 layout in a circle, denote upperbound as N=36
decide a step size, denoted as Q (Q=23 in this case) given by this formula‡
Q = findNextPrime(Math.floor(2 * N / (1 + Math.sqrt(5))))
randomly decide a starting point, e.g. number 5
start generating seemingly random nextIndex from prevIndex, by
nextIndex = (prevIndex + Q) % N
So if we put 5 in we get (5 + 23) % 36 == 28. Put 28 in we get (28 + 23) % 36 == 15.
This process will go through every number in circle (jump back and forth among points on the circle), it will pick each number only once, without repeating. When we get back to our starting point 5, we know we've reach the end.
†: I'm not sure about this term, just quoting from this answer
‡: This formula only gives a nice step size that will make things look more "random", the only requirement for Q is it must be coprime to N
Full Solution
Now let's put all the pieces together. Run the snippet to see result.
I've also includes the a counter before each log. For your case with char_list="LEDGJR", number_list="0123456789", the spaceSize for 4-digit sequence should be 6*6*10*10 = 3600
You'll observe the log bump to 5-digit sequence at 3601 😉
function euclideanDivision(a, b) {
const remainder = a % b;
const quotient = (a - remainder) / b;
return [quotient, remainder];
}
function decodeIndex(index, rowSizes) {
const rowIndexes = [];
let divident = index;
for (let i = 0; i < rowSizes.length; i++) {
const [quotient, remainder] = euclideanDivision(divident, rowSizes[i]);
rowIndexes[i] = remainder;
divident = quotient;
}
return rowIndexes;
}
function isPrime(n) {
if (n <= 1) return false;
if (n <= 3) return true;
if (n % 2 == 0 || n % 3 == 0) return false;
for (let i = 5; i * i <= n; i = i + 6) {
if (n % i == 0 || n % (i + 2) == 0) return false;
}
return true;
}
function findNextPrime(n) {
if (n <= 1) return 2;
let prime = n;
while (true) {
prime++;
if (isPrime(prime)) return prime;
}
}
function getIndexGeneratorParams(spaceSize) {
const N = spaceSize;
const Q = findNextPrime(Math.floor((2 * N) / (1 + Math.sqrt(5))));
const firstIndex = Math.floor(Math.random() * spaceSize);
return [firstIndex, N, Q];
}
function getNextIndex(prevIndex, N, Q) {
return (prevIndex + Q) % N;
}
function generatorFactory(rows) {
const rowSizes = rows.map((row) => row.length);
function getSequenceAtIndex(index) {
const tuple = decodeIndex(index, rowSizes);
return rows.map((row, i) => row[tuple[i]]).join("");
}
const spaceSize = rowSizes.reduce((m, n) => m * n, 1);
const [firstIndex, N, Q] = getIndexGeneratorParams(spaceSize);
let currentIndex = firstIndex;
let exhausted = false;
function generator() {
if (exhausted) return null;
const sequence = getSequenceAtIndex(currentIndex);
currentIndex = getNextIndex(currentIndex, N, Q);
if (currentIndex === firstIndex) exhausted = true;
return sequence;
}
return generator;
}
function getRows(chars, nums, rowsOfChars, rowsOfNums) {
const rows = [];
while (rowsOfChars--) {
rows.push(chars);
}
while (rowsOfNums--) {
rows.push(nums);
}
return rows;
}
function autoRenewGeneratorFactory(chars, nums, initRowsOfChars, initRowsOfNums) {
let realGenerator;
let currentRowOfNums = initRowsOfNums;
function createRealGenerator() {
const rows = getRows(chars, nums, initRowsOfChars, currentRowOfNums);
const generator = generatorFactory(rows);
currentRowOfNums++;
return generator;
}
realGenerator = createRealGenerator();
function proxyGenerator() {
const sequence = realGenerator();
if (sequence === null) {
realGenerator = createRealGenerator();
return realGenerator();
} else {
return sequence;
}
}
return proxyGenerator;
}
function main() {
const char_list = "LEDGJR"
const number_list = "0123456789";
const generator = autoRenewGeneratorFactory(char_list, number_list, 2, 2);
let couter = 0
setInterval(() => {
console.log(++couter, generator())
}, 10);
}
main();

Float to String Conversion - JS

So I am currently working on that function
const countSixes = n => {
if (n === 0) return 0;
else if (n === 1) return 1;
else n = (countSixes(n-1) + countSixes(n-2)) / 2;
return n;
}
And so my question is how to convert the final floating-point value into a string?
Every time after calling the function and trying to convert the float number it returns NaN
What I've Tried
"" + value
String(value)
value.toString()
value.toFixed(2)
Hope to get the answer
Thank you!
The first option works for me
<script>
const countSixes = n => {
if (n === 0) return 0;
else if (n === 1) return 1;
else n = (countSixes(n-1) + countSixes(n-2)) / 2;
return n;
}
alert(countSixes(12) + "")
</script>
The problem is really interesting. Its return NaN because when you return n as String, as the function is called recursively so it cannot perform arithmetic operations in next level.
It will never end for certain numbers like 55
function countSixes(n,firstTime=true){
if (n === 0) return 0;
else if (n === 1) return 1;
else n = (countSixes(n-1,false) + countSixes(n-2,false)) / 2;
if(firstTime) return n.toFixed(10); // return string
else return parseFloat(n.toFixed(10)); // return float
}
You could convert the final value to a string with the wanted decimals.
const countSixes = n => {
if (n === 0) return 0;
if (n === 1) return 1;
return (countSixes(n - 1) + countSixes(n - 2)) / 2;
}
console.log(countSixes(30).toFixed(15));

How to count number of ways to parenthesize boolean expression string to evaluate to desired result

Straight out of CTCI, 8.14: Given a boolean expression consisting of the symbols 0 (false), 1 (true), & (AND), | (OR), and ^(XOR), and a desired boolean result value result, implement a function to count the number of ways of parenthesizing the expression such that it evaluates to result.
I'm attempting a brute force approach that calculates every single possible combo, if matches desired result, add it to an array(combos) and return that result length. It seems to work for most expressions, but not the 2nd example given. What do I seem to be missing?
function countEval(s, goalBool, combos = []) {
// on first call make s into array since theyre easier to work with
if (!(s instanceof Array)) {
// and turn 1s and 0s into their bool equivalent
s = s.split('').map((item) => {
if (item === '1') {
return true;
} else if (item === '0'){
return false;
} else {
return item;
}
});
}
if (s.length === 1 && s[0] === goalBool) {
combos.push(s[0]); // can be anything really
} else {
for (let i = 0; i < s.length - 2; i = i + 2) {
// splice out the next 3 items
const args = s.splice(i, 3);
// pass them to see what they evaluate too
const result = evalHelper(args[0], args[1], args[2]);
// splice that result back in s array
s.splice(i, 0, result);
// pass that array to recurse
countEval(s, goalBool, combos);
// remove said item that was just put in
s.splice(i, 1);
// and reset array for next iteration
s.splice(i, 0, ...args);
}
}
return combos.length;
}
function evalHelper(a, op, b) {
if (op === '|') {
return a || b;
} else if (op === '&') {
return a && b;
} else if (op === '^') {
return a !== b;
}
}
With the 2 examples given it works for the first one, but not the second...
console.log(countEval('1^0|0|1', false)); // 2, correct
console.log(countEval('0&0&0&1^1|0', true)); // 30, should be 10!?!?!
The Bug
Your program is not taking into account overlap.
Example
Consider your program when s = '1|1|1|1'.
In one of the depth-first search iterations, your algorithm will make the reduction s = (1|1)|1|1. Then in a deeper recursive level in the same search, your algorithm will make the reduction s = (1|1)|(1|1). Now s is fully reduced, so you increment the length of combos.
In a different depth-first search iteration, your algorithm will first make the reduction s = 1|1|(1|1). Then in a deeper recursive level in the same search, your algorithm will make the reduction s = (1|1)|(1|1). Now s is fully reduced, so you increment the length of combos.
Notice that for both cases, s was parenthesized the same way, thus your program does not take into account overlap.
A Better Solution
A lot of times, when a problem is asking the number of ways something can be done, this is usually a big indicator that dynamic programming could be a potential solution. The recurrence relation to this problem is a bit tricky.
We just need to pick a "principle" operator, then determine the number of ways the left and right side could evaluate to true or false. Then, based on the "principle" operator and the goal boolean, we can derive a formula for the number of ways the expression could evaluate to the goal boolean given that the operator we picked was the "principle" operator.
Code
function ways(expr, res, i, j, cache, spaces) {
if (i == j) {
return parseInt(expr[i]) == res ? 1 : 0;
} else if (!([i, j, res] in cache)) {
var ans = 0;
for (var k = i + 1; k < j; k += 2) {
var op = expr[k];
var leftTrue = ways(expr, 1, i, k - 1, cache);
var leftFalse = ways(expr, 0, i, k - 1, cache);
var rightTrue = ways(expr, 1, k + 1, j, cache);
var rightFalse = ways(expr, 0, k + 1, j, cache);
if (op == '|') {
if (res) {
ans += leftTrue * rightTrue + leftTrue * rightFalse + leftFalse * rightTrue;
} else {
ans += leftFalse * rightFalse;
}
} else if (op == '^') {
if (res) {
ans += leftTrue * rightFalse + leftFalse * rightTrue;
} else {
ans += leftTrue * rightTrue + leftFalse * rightFalse;
}
} else if (op == '&') {
if (res) {
ans += leftTrue * rightTrue;
} else {
ans += leftFalse * rightFalse + leftTrue * rightFalse + leftFalse * rightTrue;
}
}
}
cache[[i, j, res]] = ans;
}
return cache[[i, j, res]];
}
function countEval(expr, res) {
return ways(expr, res ? 1 : 0, 0, expr.length - 1, {});
}

Javascript toFixed function

The expected result of:
(1.175).toFixed(2) = 1.18 and
(5.175).toFixed(2) = 5.18
But in JS showing:
(1.175).toFixed(2) = 1.18 but
*(5.175).toFixed(2) = 5.17*
How to rectify the problem?
It's not a bug. It's related to the fact numbers aren't stored in decimal but in IEEE754 (so 5.175 isn't exactly stored).
If you want to round in a specific direction (up) and you consistently have numbers of this precision, you might use this trick :
(5.175 + 0.00001).toFixed(2)
You could always try using round, instead of toFixed.
Math.round(5.175*100)/100
You could even try putting it in some prototype method if you want.
Created a jsBin that implements a simple prototype on Number.
Number.prototype.toFixed = function(decimals) {
return Math.round(this * Math.pow(10, decimals)) / (Math.pow(10, decimals));
};
It's because the numbers are stored as IEEE754.
I would recommend you to use the Math class (round, floor or ceil methods, depending on your needing).
I've just created a class MathHelper that can easily solve your problem:
var MathHelper = (function () {
this.round = function (number, numberOfDecimals) {
var aux = Math.pow(10, numberOfDecimals);
return Math.round(number * aux) / aux;
};
this.floor = function (number, numberOfDecimals) {
var aux = Math.pow(10, numberOfDecimals);
return Math.floor(number * aux) / aux;
};
this.ceil = function (number, numberOfDecimals) {
var aux = Math.pow(10, numberOfDecimals);
return Math.ceil(number * aux) / aux;
};
return {
round: round,
floor: floor,
ceil: ceil
}
})();
Usage:
MathHelper.round(5.175, 2)
Demo: http://jsfiddle.net/v2Dj7/
Actually I think this is a bug in the implementation of Number.prototype.toFixed. The algorithm given in ECMA-262 20.1.3.3 10-a says to round up as a tie-breaker. As others have mentioned, there probably isn't a tie to break due to floating point imprecisions in the implementation. But that doesn't make it right :)
At least this behavior is consistent across FF, Chrome, Opera, Safari. (Haven't tried others.)
FWIW, you can actually implement your own version of toFixed per the spec in JS and that behaves as you would expect. See http://jsfiddle.net/joenudell/7qahrb6d/.
Kippie
your solution has problems
one of them
39133.005.toFixed(2) => 39133
var Calc = function () {
var self = this;
this.float2Array = function(num) {
var floatString = num.toString(),
exp = floatString.indexOf(".") - (floatString.length - 1),
mant = floatString.replace(".", "").split("").map(function (i) { return parseInt(i); });
return { exp: exp, mant: mant };
};
this.round2 = function (num, dec, sep) {
var decimal = !!dec ? dec : 2,
separator = !!sep ? sep : '',
r = parseFloat(num),
exp10 = Math.pow(10, decimal);
r = Math.round(r * exp10) / exp10;
var rr = Number(r).toFixed(decimal).toString().split('.');
var b = rr[0].replace(/(\d{1,3}(?=(\d{3})+(?:\.\d|\b)))/g, "\$1" + separator);
r = (rr[1] ? b + '.' + rr[1] : b);
return r;
};
this.toFixed10 = function (f, num) {
var prepareInt = self.float2Array(f),
naturalInt = prepareInt.mant,
places = Math.abs(prepareInt.exp),
result = prepareInt.mant.slice(),
resultFixedLenth;
// if number non fractional or has zero fractional part
if (f.isInt()) {
return f.toFixed(num);
}
// if the number of decimal places equals to required rounding
if (places === num) {
return Number(f).toString();
}
//if number has trailing zero (when casting to string type float 1.0050 => "1.005" => 005 <0050)
if (places < num) {
return Number(f).round2(num);
}
for (var e = naturalInt.length - (places > num ? (places - num) : 0), s = 0; e >= s; e--) {
if (naturalInt.hasOwnProperty(e)) {
if (naturalInt[e] > 4 && naturalInt[e - 1] < 9) {
result[e] = 0;
result[e - 1] = naturalInt[e - 1] + 1;
break;
} else if (naturalInt[e] > 4 && naturalInt[e - 1] === 9) {
result[e] = 0;
result[e - 1] = 0;
result[e - 2] = naturalInt[e - 2] < 9 ? naturalInt[e - 2] + 1 : 0;
} else if (e === 0 && naturalInt[e] === 9 && naturalInt[e + 1] === 9) {
result[e] = 0;
result.unshift(1);
} else {
break;
}
}
}
if (places - num > 0) {
resultFixedLenth = result.slice(0, -(places - num));
} else {
for (var i = 0, l = num - places; i < l; i++) {
result.push(0);
}
resultFixedLenth = result;
}
return (parseInt(resultFixedLenth.join("")) / Math.pow(10, num)).round2(num);
};
this.polyfill = function() {
if (!Array.prototype.map) {
Array.prototype.map = function (callback, thisArg) {
var T, A, k;
if (this == null) { throw new TypeError(' this is null or not defined'); }
var O = Object(this), len = O.length >>> 0;
if (typeof callback !== 'function') { throw new TypeError(callback + ' is not a function'); }
if (arguments.length > 1) { T = thisArg; }
A = new Array(len);
k = 0;
while (k < len) {
var kValue, mappedValue;
if (k in O) {
kValue = O[k];
mappedValue = callback.call(T, kValue, k, O);
A[k] = mappedValue;
}
k++;
}
return A;
};
}
};
this.init = function () {
self.polyfill();
Number.prototype.toFixed10 = function (decimal) {
return calc.toFixed10(this, decimal);
}
Number.prototype.round2 = function (decimal) {
return calc.round2(this, decimal);
}
Number.prototype.isInt = function () {
return (Math.round(this) == this);
}
}
}, calc = new Calc(); calc.init();
this works good)
obj = {
round(val) {
const delta = 0.00001
let num = val
if (num - Math.floor(num) === 0.5) {
num += delta
}
return Math.round(num + delta)
},
fixed(val, count = 0) {
const power = Math.pow(10, count)
let res = this.round(val * power) / power
let arr = `${res}`.split('.')
let addZero = ''
for (let i = 0; i < count; i++) {
addZero += '0'
}
if (count > 0) {
arr[1] = ((arr[1] || '') + addZero).substr(0, count)
}
return arr.join('.')
}
}
obj.fixed(5.175, 2)
// "5.18"

Categories