Not able to understand javascript behaviour - javascript

I am trying to execute the following code
var n = 100;
var sum =0;
while(n>0)
{
sum = sum + n%10;
n = n/10;
}
console.log(sum);
The result should be 1 but javascript is returning
1.1111111111111112
Also, when I ran individual statements it is giving perfectly fine result,
what could be the possible reason?

The result it is giving is correct -
Lets go into while loop
For first iteration n=100 so n%10 = 0 and sum = 0, after first loop sum = 0 and n = 10
In second iteration n%10 = 0 and sum = 0,
after second iteration sum = 0 and n = 1
For third iteration n%10 = 1 and sum =0,
after third iteration sum = 1 and n = 0.1
For fourth iteration n%10 = 0.1 and sum = 1,
after fourth iteration sum = 1.1 and n = 0.01
and so on so forth
finally the answer would be 1.1111111111....... tending to infinity so it becomes 1.1111111111111112
Hope this helps
EDIT
If you want final answer as 1, intialise n as 0.9(n = 0.9)

No, the result won't be 1. Notice that your loop is dividing n by 10 every iteration, and that the continuing condition is n > 0, which will take many iterations till it happens:
n=100, n%10=0
n=10, n%10=0
n=1, n%10=1
n=0.1, n%10=0.1
n=0.01, n%10=0.01
...
So, the result is correct: 1.1111111... The 2 at the end is no more than a rounding decimal error (minimal).

Related

Maximum subarray problem - min value solution?

Have you ever felt like your head wasn't meant for an algorithm?
I tried solving the maximum subarray problem and I came across this solution on Codewars:
var maxSequence = function(arr){
var min = 0, ans = 0, i, sum = 0;
for (i = 0; i < arr.length; ++i) {
sum += arr[i];
min = Math.min(sum, min);
ans = Math.max(ans, sum - min);
}
return ans;
}
console.log(maxSequence([-2, 1, -3, 4, -1, 2, 1, -5, -4]));
I understand how to solve this problem with a linear time complexity using Kadane's algorithm:
var maxSequence = function(arr){
let max = 0;
let localMax = 0;
for (let i = 0; i < arr.length; i++) {
localMax = Math.max(localMax + arr[i], arr[i]);
max = Math.max(localMax, max);
}
return max;
}
console.log(maxSequence([-2, 1, -3, 4, -1, 2, 1, -5, -4]));
But I can't make sense of why the first solution works. I simply can't grasp the idea behind it. I feel like a need a little help getting over the hump.
Edit: Here's a Codepen with some examples
The algorithm you provided is doing the same thing, in a more complex manner though. In order to explain it properly, I will compare the Codewars algorithm you provided with the Kadanes algorithm in various steps of their execution.
Let us consider the array:
[2 -4 3 2 6 -10 -12 20]
Here is the Codewars algorithm you provided:
var maxSequence = function(arr){
var min = 0, ans = 0, i, sum = 0;
for (i = 0; i < arr.length; ++i) {
sum += arr[i];
min = Math.min(sum, min);
ans = Math.max(ans, sum - min);
}
return ans;
}
Here is the implementation of Kadanes algorithm mentioned in Wikipedia:
def max_subarray(numbers):
"""Find the largest sum of any contiguous subarray."""
best_sum = 0 # or: float('-inf')
current_sum = 0
for x in numbers:
current_sum = max(0, current_sum + x)
best_sum = max(best_sum, current_sum)
return best_sum
First step:-
sum changes to 2 and min remains the same. The ans changes to 2.
Second step:-
sum changes to -2 and min changes to -2. The ans is still 2. An interesting thing to notice here, according the implementation of Kadanes algorithm by Wikipedia, there in the second stage the value of current_sum will change to 0 which is the correct way to proceed.
However in the codewars implementation, the value of sum is still -2. If you notice a little more carefully though, you will observe that the value of sum-min is 0 in the codewars implementation. This is a really important point to notice. Instead of changing sum to 0 when its value reaches less than 0. We store the minimum number that must be substracted from sum to make the net sum 0. This value is stored in min and which also explains why it is named so.
Here is a record of the value of variables so far:
sum min ans
2 0 2 //ans = max(0, 2-0)
-2 -2 2 //ans = max(2, -2+2)
Third step:-
The sum changes to 1. min still remains the same. The ans changes to 3 which is the correct. How did this happen though?
In the Kadanes algorithm, you change the value of current_sum to 3 at this stage. In the codewars implementation, instead of changing sum to 3, what they have done is used a min variable which I repeat again stores the number that should be substracted from answer so that we obtain the same value as we do in current_sum. This is more clear from this part of the algorithm.
ans = Math.max(ans, sum - min); //sum-min is current_max
Here when we substract the min from your sum. It neutralizes that extra negative in your answer. In this array A, the extra negative is 2 + (-4) = -2. In each of the following steps, we will observe that here sum is not containing the maximum continuous subarray sum. Maximum continuous subarray sum there is stored in sum - min. This is the key of this algorithm. sum-min is the current_sum here. Here are the following steps:
sum min ans
1 -2 3 //ans = max(2, 1+2)
3 -2 5 //ans = max(3, 3+2)
9 -2 11 //ans = max(5, 9+2)
-1 -2 11 //ans = max(11, -1+2)
It is interesting to observe that even though the value of sum is negative in the last step, the value of min does not change. Why is that? The answer is it does not need to. If you look at sum-min is this case, it is 1 and not less than 0. Hence there is a possibility that if sufficient positive numbers follow after the current index in A, the value of sum-min might exceed the current value of ans. If you dry run Kadanes algorithm till this step, you will notice that even there the value of current_sum will not change to 0 at this stage, it will be 1.
Remaining steps:-
sum min ans
-1 -2 11 //ans = max(11, -1+2)
-13 -13 11 //ans = max(11, -13+13)
7 -13 20 //ans = max(11, 7+13)
The most important point in this implementation, sum-min here is analogous to current_sum of Kadanes algorithm.
I should also mention that the Kadanes algorithm and codewars algorithm you provided will not work if the input array consists of all negative numbers. Both are not meant for it. There is a small implementation difference in the Kadanes algorithm if you want it to work for array consisting of all negative numbers (initialize current_sum to A[0]).
Do comment if you face any problems in understanding my explanation.
I don't think the the Codewars algorithm will work for every test case.
Following are the test cases where this algorithm will fail:
Test Case 1: arr = [-1]
Test Case 2: arr = [-1, -2]
For both the test cases, the algorithm under test gives an output equal to 0, which is not the correct answer.
PS: I have checked the Codewars problem. The test cases for the problem are not yet comprehensive and this problem has issues.
So for the time being, Kadane's algorithm is a good choice to solve the problem in linear time complexity.

how does Increment and Decrement work in Javascript

Can someone please explain why this function returns 0?
Shouldn't it return 1 since n++ = n and --n = n-1?
var x = function(n) {
return n++ - --n;
};
n++ is a post-increment, so first return the value, then will add 1 to it:
var n = 1;
console.log(n++); //shows 1, increments `n` to 2
console.log(n);//shows 2
console.log(n++); //shows 2, increments `n` to 3
--n is a pre-decrement - the value is first reduced by 1 and then return
var n = 3;
console.log(--n); //shows 2, `n` is already set to 2
console.log(n);//shows 2
console.log(--n); //shows 1, `n` is already set to 1
Here is an example to explain how this is being evaluated: When it's being evaluated:
var x = function (n) {
return n++ - --n;
};
x(5);
0. First n = 5 we go from there:
n = 5
n++ - --n
1. The post-increment has the highest precedence here, so we start with that.
2.n++ will return 5 but also change n to 6. So if we resolve that we have:
n = 6
5 - --n
3. Next in the order of precedence is the the pre-decrement operation.
4. --n will reduce n and return the new value, so:
n = 5
5 - 5
5. Finally, we solve the subtraction and get 0.
n++ - --n
if n = 10, then the value of (n++) is 10, but after that n is increased by one.
So n = 11 after evaluating (n++). if n = 11, (--n) = 10.
n++ - --n
--- ----- ---
10 n = 11 10
so the result is 0
This is a left to right evaluation and the incrementation is done after its value is used.
So lets assume the input is 10
Evaluate to 10 then increase then decrease so 10 - 10 the final expression.
Let's say n = 10
1. n++ will return the original value that n held before being incremented. And before going to the next operation n will be 11.
2. --n will decrease increased value(11) by 1, and then return the decreased value.
3. Finally, 10 - 10 is 0
Arithmetic Operations

Why does this function return NAN

If I use <= instead of <, I'll get NaN, why?
function addArgs(){
var sum = 0, count = 0;
while(count <= arguments.length){
sum += arguments[count];
count++;
}
return sum;
}
in the last iteration of your loop, count is arguments.length, therefore arguments[count] === arguments[arguments.length] === undefined, and sum += undefined results in sum === NaN
Suppose your argument is 3 elements:
arguments = [0, 1, 2]
Your count will iterate as 0 => 1 => 2 => 3 (and on 3rd you are out of bound of the array, since it has 3 elements, but indexed starting with 0.
That's basics of iterating through loop.
When you iterate through a list and use the index to access the items of the list (like you're doing), you always iterate up to length - 1 or < length. The reason is that the list index starts from zero, not one. For instance, a list of 3 items has it's length equals 3 and the indexes of its items are 0, 1, and 2. There is no item with index 3, so if you iterate up to length or <= length, the counter will reach 3 in the last iteration and the attempt to retrieve the item with the index 3 will fail and return undefined.
Finally, adding the undefined to the sum will results in a NaN because undefined is not a number.
It seems that arguments[count] is not a number (NaN). In Javascript, when the second argument in an expression is not a number, the first one is also treated as not a number.
Thus, sum ends up the function being treated as another data type.
http://www.w3schools.com/js/js_datatypes.asp
All iterations start from 0(Also, count = 0 in your code). So, max count equals arguments.length-1.
addArgs(2,5,8); -> arguments[0] = 2; arguments[1] = 5; arguments[2] = 8;
Besides that, you can use <= when count starts from 1
function addArgs(){
var sum = 0, count = 1;
while(count <= arguments.length){
sum += arguments[count-1];
count++;
}
return sum;
}
addArgs(2,3,4);//9

Why does my factorial function always return one?

I am trying to write a piece of code to solve a Coderbyte challenge, to calculate a number's factorial. Every time I run it, the factorial generated is one. What am I doing wrong?
var num
var array1 = new Array();
function FirstFactorial(num) {
for (var i = num; i>0; i--){ // 8 , 7, 6 , 5
for (var y = 0; y<num ; y++){ // 0, 1, 2, 3, 4
array1[y]=i; // we have an array that looks like [8,7,6,5,4,3,2,1]
};
};
var sum = 1
for (var x = 0; x<array1.length; x++){ // now I want to run up that array, reading the #s
sum = sum * array1[x];
return sum;
};
return sum
};
A few issues.
1/ This is minor but, when you multiply two numbers, you get a product, not a sum.
2/ You returned the value from within the loop which would mean, even if you fixed the other problems, it would return prematurely without having multiplied all the numbers.
3/ Your nested loop does not fill your array the way you describe, you should check it after population. Think about your loops expressed as pseudo-code:
for i = num downto 1 inclusive:
for y = 0 to num-1 inclusive:
array1[y] = i
You can see that the inner loop is populating the entire array with the value of the current i. So the last iteration of the outer loop, where i is one, sets the entire array to ones.
4/ In any case, you don't need an array to store all the numbers from 1 to n, just use the numbers 1 to n directly. Something like (again, pseudo-code):
def fact(n):
prod = 1
for i = 2 to n inclusive:
prod = prod * i
return prod
This is a much easier way to calculate the factorial of a number.
function factorial(num)
{
if(num === 1)
{
return num;
}
return num * factorial(num - 1);
}
However to fix your code you need to fix the initial loop that loads the numbers into the array. as well as remove the return statement in the bottom loop. Like so.
function FirstFactorial(num) {
for (var i = num; i>0; i--) {
array1[num - i] = i;
};
var sum = 1
for (var x = 0; x < array1.length; x++){ // now I want to run up that array, reading the #s
sum = sum * array1[x];
};
return sum
};

Sorting out numbers in for loops

So I am determining which is a prime number and which isn't, but I am just not understanding how it ends up with the correct output.
So the first starts at 2 and loops by 1 to 100. Easy.
But the second starts at 0, and loops by y + itself, this would make sense, but in determining the primes, it should mess up, atleast I thought
it's like: 1+3 = 4 or 2 + 4 = 6 or 3 + 5 = 8
and that works, but what happens to let's say the 15? that isn't a prime number.
How is numbers like that sorted in the loop?
var prim = [];
var notprim = [];
for(var x = 2; x <= 100; x++){
if(!notprim[x]){
prim.push(x);
for(var y = 0; y <= 100; y = y+x){
notprim[y] = true;
document.write(y);
}
}
}
You have an Array notprim that you can imagine as [undefined × 100], and !!undefined === false, i.e. undefined is falsy
If for some number n you have notprim[n] falsy, you assume it means n must be a prime number and add it to another Array, prim
Then you set all multiples of n to be truthy in notprim, i.e. if n is 3, you set notprim[n * x] = true;, i.e. 0, 3, 6, 9, 12, 15, etc
You then look for the next falsy index in notprim to start again
The reason the first loop starts at 2 is because 2 is the first prime number, starting from 1 or 0 would cause the assumption that "notprim[n] falsy means n is a prime number" to fail
Great, but what about the other loop? Well, one way of going through n * x is to add n to itself x times. When you're thinking of it this way, you can then limit how high you go without knowing a maximum multiplier in advance by looking at the running total, for example in a for loop
for (t = 0; t <= 100; t = t + n)
// t ∈ nℤ, 0 <= t <= 100
but what happens to lets say the 15?
When you've found the prime number 3, you then flag all multiples of 3 to be excluded from your search for primes. 15 is a multiple of 3 so gets flagged as not a prime. Hence your if (!notprim[x]) does not pass
You can reduce the number of iterations this code needs by excluding 0 and x from the second for loop; i.e. begin from the index y = 2 * x

Categories

Resources