What is the Infinity property used for in Javascript? - javascript

Why is the Infinity property used as a command (rather than a result)
For example, this code below works, but the result isn't what I expected.
alert(isOdd(Infinity));
function isOdd(num) { return num%2==1; }

MDN REFERENCE
Infinity is a property of the global object, i.e. it is a variable in
global scope.
The initial value of Infinity is Number.POSITIVE_INFINITY. The value
Infinity (positive infinity) is greater than any other number. This
value behaves mathematically like infinity; for example, any positive
number multiplied by Infinity is Infinity, and anything divided by
Infinity is 0.
First what does this mean? In essence infinity is a concept not an actual value. Mathematics is based on concepts not values. For instance a number isn't a value, a numeral is.
The number 7 is the concept of the intended value, Romans wrote it as VII, in standard form (BASE-10) you write it as 7. In binary(BASE-2) you write it as 111. If you want to use a triangle or any other mark that is fine also as long as the concept is applied correctly.
Now that you know that, Infinity is simply the concept of being greater than any other number. It holds no value. The only reason that the basic concept of an infinity loops means to run forever is because in concept it means that whatever numeral iteration of that loop you are in (whether 1 or a million) infinity will always be greater than that number.
There are many methods to applying concepts in coding which is why everyone's code is ran differently but for example:
SAMPLE TAKEN FROM w3schools:
function findMax(x) {
var i;
var max = -Infinity;
for(i = 0; i < arguments.length; i++) {
if (arguments[i] > max) {
max = arguments[i];
}
}
return max;
}
document.getElementById("demo").innerHTML = findMax(1, 123, 500, 115, 44, 88);
In the site's example they pass the argument of 6 values to the function findMax
findMax(1, 123, 500, 115, 44, 88);
They are then using a loop to stop at the parameters length. In the loop they are reassigning the max value from the concept of infinity to a value and if greater than that value when looped again the max value is then changed to the new high value.
Why is this important? Because in the example they use the concept of negative infinity which is simply the values of infinity decremented negatively. One could easily argue that 0 could replace -Infinity but they'd be wrong. This is why.
What if your value range is dependent upon negative values also being passed in the formula above? What if all you have is negative values that were dynamically captured from user input or another function?
Consider findMax was findMax(-1, -10, -15, -20);
0 would give a false output that it was the correct max value which wouldn't be what you wanted. You'd want -1 one to be the output. There are other methods to achieving the solution but for the sake of Infinity concept discussion I will end here.
I hope this sheds more light on the process of Infinity concept.

Infinity is a property of the global object that holds a numeric value representing the mathematical concept of infinity. I don't know any normal definition by which it could be called a "command."
With regard to your edit, that should return false (I ran it to confirm this suspicion, and it did on my browser). This is correct, as infinity is not normally considered an odd number.

Related

Why -Infinity is like a base for comparing numbers to return max?

In this code i can't seem to understand why -Infinity is behaving like a base so when compared to it returns the biggest number from an array of numbers.
function max(...numbers) {
let result = -Infinity;
for (let number of numbers) {
if (number > result) result = number;
}
return result;
}
It is confusing at first and probably in your mind a solution would sound like this:
let result = 0;
The problem is that when we want to find the MAXIMUM value of an array we need to compare every element with each other. It is more like a "habit" that we set the MAXIMUM to -INFINITY. That simply means that the biggest element so far is the lowest possible number that we can express. Does it make sense? We simply assume that the biggest number we will every find is -Infinity. Then we compare the elements from the array with this base number(in our case -Infinity) and if we were false (and probably we were) then we replace -Infinity with the next number that's bigger than our current value. We do that for the whole range of numbers and that's how we find the Maximum element.
You can pick multiple elements as the starting point, but never pick a number entered by yourself( you should do that ONLY if the exercise asks so).
If you would pick for example:
let result = 0;
then you might have a problem. Maybe the numbers are all negative, for example [-3,-13,-5,13,-99] but you already set the biggest number to 0 so every comparation would be wrong and useless.
So, keep in mind that is a good practice, in this case, to set the base value to -Infinity or if you would like to take another approach then set the base value to the first element in the array.
In using this numbers to find the max of a series of numbers ,you loop through an array of numbers, each number will be compared to -infinity. And since the program is running from left to right the result will update itself each time it finds a bigger number. I tried this comparison method with an actual number.
let edge;
let array1 = [1, 2, 3, 4, 5, 6, 8, 9, 100, 200];
function maxwell(){
for(let checker of array1){
if(checker > 2)edge = checker;
}return edge;
}console.log(maxwell())

Comparing big numbers in Javascript

I've got two numbers that I want to compare. The numbers in the following example are the result of 26^26 computed in two different systems. One of which is my javascript code.
However, when comparing the two numbers I end up with something like this:
AssertionError [ERR_ASSERTION]: 4.0329146112660565e+26 == 4.0329146112661e+26
They're obviously not equal, but theoretically they should.
What's the proper way to perform equality on big numbers in javascript (even if it's an approximation)?
If what you're trying to do is determine if two numbers are practically equivalent you'll have to come up with your margin of error. One way to do this is to compute the difference between the numbers and then determine if that difference is significant or not.
So, taking your numbers from before, we could evaluate the difference between these numbers through subtraction. Since we don't really care about the sign of this difference, I'll go ahead and get the absolute value of the difference.
Math.abs(4.0329146112660565e+26 - 4.0329146112661e+26) === 4329327034368
(Sidenote: Now is not the time to explain why, but the == operator in JavaScript has confusing and error-prone behavior, use === when you want to compare values.)
That difference is a HUGE number, but related to how big our numbers are in the first place, it's rather insignificant. Intuitively, I'm tempted to divide the difference by the smallest of our original numbers like so:
4329327034368 / 4.0329146112660565e+26 === 1.0734983136696987e-14
That looks like a pretty small number. Repeat that same operation with a bunch of values and you should be able to determine what you want your margin of error to be. Then, all you'll have to do is perform the same operations with arbitrary numbers and see if that "difference ratio" is small enough for you.
function similar(a, b) {
let diff = Math.abs(a - b);
let smallest = Math.min(Math.abs(a), Math.abs(b));
let ratio = diff / smallest;
return ratio < MARGIN_OF_ERROR;
}
Now I just came up with that way of determining the importance of the difference between two numbers. It might not be a very smart way to compute it, it might be appropriate to some situations and not to others. But the general idea is that you'll have to make a function that determines if two values are close enough with your own definition of "close".
Be aware though, JavaScript is one of the worst languages you can be doing math in. Integers become imprecise when they go beyond Number.MAX_SAFE_INT (which seems to be 9007199254740991 according to Chrome, not sure if it varies between browsers or if that's a standardized constant).
Update: If your target engine is es2020 or above, you can use the new BigInt javascript primitive, for numbers higher than Number.MAX_SAFE_INTEGER
BigInt(4.0329146112660565e+26) === BigInt(4.0329146112661e+26)
//false
See more information in MDN
var a = 4.0329146112660565e+26;
var b = 4.0329146112661e+26;
a = Math.round(a/10e+20)*10e+20
b = Math.round(b/10e+20)*10e+20
a == b;
I would suggest to use one of big numbers library:
big.js (https://www.npmjs.com/package/big.js)
Example:
var x = new Big('4.0329146112660565e+26');
var y = new Big('4.0329146112661e+26');
// Should print false
console.log('Comparision result' + x.eq(y));
big-numbers (https://www.npmjs.com/package/big-numbers)
Example:
var x = bn.of('4.0329146112660565e+26');
var y = bn.of('4.0329146112661e+26');
// Should print false
console.log('Comparision result' + x.equals(y));

Check if two objects are equal when they have floating point values?

Writing some test cases for my Javascript program that deals with binary and right now I'm just using stringify to check if the value and expected values are equal:
JSON.stringify(val) === JSON.stringify(expected)
This works fine except for when I have floating point values. This is what happens:
Given Value: [10,20,30,32.400001525878906,{"test":3,"asdf":23}]
Expected Value: [10,20,30,32.4,{"test":3,"asdf":23}]
Test Failed!
So I guess I can't use stringify anymore to check if my two objects/arrays are equal. What's a good way to check if two potentially deeply nested objects/arrays are equal while also taking in to account floating point values? That is, two floating point values should be considered equal if they are 99.99% the same or whatever.
You'll need to test each element in the array in order, and you'll need to do it recursively for objects. This is typically known as a deep comparison or deep equality. You should be able to do this using a recursive function that checks the type(s) of the comparands.
When comparing floating point values, you'll want to use a tolerance. You do this by taking the absolute value of subtracting the two numbers from each other, and then comparing that to either a fixed tolerance value of your choosing, or a small number known as an epsilon.
In JavaScript, the machine epsilon is available as Number.EPSILON, and is defined to be the difference between 1 and the smallest number that is greater than 1 and can be represented as a Number. Similar constants are available in most languages and are typically used for tolerance-based comparisons.
Tolerance-based comparison turns floating point comparisons from simple equality into a subtract and compare. If you'd normally write
if (a === b) { ... }
you'd write that using the absolute value and a tolerance to eliminate floating point weirdness:
var tolerance = Number.EPSILON;
if (Math.abs(a - b) < tolerance) { ... }
If the difference between a and b is smaller than tolerance, you treat them as equal.
For a more nuanced (but possibly overkill for your case) approach, see The Floating Point Guide's section on comparison. The implementation presented there is in Java, but is likely portable to JavaScript without much effort.

Factoralize a Number in JavaScript

I'm currently taking a course on Free Code Camp and it's asking me return a factorial for any given number. However, I'm kind of stuck on the question (please forgive me, math isn't my strong point, haha). Here's what it asks:
If the integer is represented with the letter n, a factorial is the product of all positive integers less than or equal to n.
Factorials are often represented with the shorthand notation n! For example: 5! = 1 * 2 * 3 * 4 * 5 = 120f
And here's the starting code:
function factorialize(num) {
return num;
}
factorialize(5);
I'm not looking for a direct answer to the question, but I just really want to know how to start. Thanks for any help in advance!
There is two ways of doing that. First one in the loop and second one is in recursive function.
Loop version is like that:
function factorialize(num) {
for(var answer=1;num>0;num--){
answer*=num;
}
return answer;
}
And recursive one is like that.
function factorialize(num) {
if(num===0){
return 1;
}
else{
return num*factorialize(num-1);
}
}
Both of them will work with all positive integers.
function factorialize(num) {
var myNum = 1;
for (i=1; i<=num;i++){
myNum = myNum * i;
}
return myNum;
}
factorialize(5);
First I created a var to hold our answer (myNum).
Then I created a loop that started at 1 and up to (and including) the value of the number we are factorializing...
As the loop runs, we multiply myNum to the value of i, saving the new value as myNum, so it will be multiplied by the next number in the loop...
Once the loop has finished, we return our answer using the "return myNum".
Note: This response explains which type of loop to use and hints on how to format the loop to get a factorial of 5, to get the basic format before using num
Given the example of 5! = 1 * 2 * 3 * 4 * 5 = 120, you can see there is a pattern of numbers that start at 1, end at 5, and increment by 1. You can also see that for each number between 1 and 5, you need to multiply by the next one, over and over again, in order to get the factorial.
A for loop is used to repeat a specific block of code a known number of times. In this case, you know the number of times is 5 (aka 1,2,3,4,5). The specific block of code is what you'll need to figure out based on the answer you are trying to get (which in this case is 5! = 1*2*3*4*5 = 120).
For Loop Hints:
When thinking about how to write the for loop's conditions:
Start the incrementing at 1, end the incrementing at 5, and increment by 1 (1,2,3,4,5)
When writing the block of code that will act upon each number, think about the relationship each number needs to have so your code essentially does this:
1*2*3*4*5

Heavily packed javascript, multiple questions from 219-byte (canvas, bitwise,...)

I came across a website today. It was a challenge of some developers about making the smallest game possible with certain requirements, and they released the final code of unbelievable size of 219 bytes and runnable on Chrome 17 (one of the requirements). I tried to explore the code (with the explanation provided from the site) and do researches on codes I didn't comprehend. However, the code was packed too heavily to my knowledge, so I am seeking for some helps.
Here is the code, after beautified:
<body id=b onkeyup=e=event onload=
z=c.getContext('2d');
z.fillRect(s=0,0,n=150,x=11325);
setInterval("
0<x%n
&x<n*n
&(z[x+=[1,-n,-1,n][e.which&3]]^=1)?
z.clearRect(x%n,x/n,1,1,s++)
:b.innerHTML='GameOver:'+s
",9)>
<canvas id=c>
The game is named "Tron", and just like classic snake game (without apple).
Anyway, here are my questions:
1) How can they select element with id 'c' without using getElementById() rather than a simple c
Look at the bottom of the code, there is a canvas with <canvas id=c>. I understand that advanced browsers will automatically fix the quotes "" for the id="c". However, when a function is called in onload event, it assigns z = c.getContent('2d'); and directly refers to the canvas without even applying anything such as document.getElementById(). Also the same when they referred to <body id=b>. How is that possible? Under which circumstances am I able to do similarly?
2) Will replacing parameters of a functions by quick assigning variables affect the function at all? If it does, how will it be calculated?
Particularly, take a look of the third line:
z.fillRect(s = 0, 0, n = 150, x = 11325);
I understand to the most basic level, fillRect() requires 4 parameters fillRect(x-cor, y-cor, width, height). However, the code above produces a rectangle 150x150. First of all, I read the description and they claimed that by default, the code would produce a rectangle 300x150, so I assumed that the assigning short functions would actually assign nothing to the parameters of the parent function. I did a test, and replaced n = 150 by n = 200. Weirdly enough, it produces a rectangle 200x150, so once again I agree that n = 150 did assign 150 to that slot. Hence, the code above can be written as:
z.fillRect(0, 0, 150, 11325);
However, another problem comes. Why isn't its height 11325px but 150px instead? I thought it was reset to default because 11325 excessed the handling of browsers, so I changed it to 500 instead; and it produced the same problem.
So generally, when you do short assigning inside a function (for instance: someCustomFunction.call(s = 1)), what really happens there? If nothing happens, why did the rectangle in the example above changed its size when replacing n = 200 but not when x = 200?
Additional question: this question is not the question I am really into, because it is too personal, but I would love to know. The source states that "x is going to be the tron's position, and is set to 11325 (11325 = 75 x 75 + 75 = center of the grid)", how does this kind of one-number-represents-position work?
3) What in the world does it mean?
This is the most headache part to me, because the author packed it too smartly.
&(z[x+=[1,-n,-1,n][e.which&3]]^=1)?
I broke it up, and figured that it was actually z[]^=1 in order to check the condition for the later ? : operators. But first:
What does ^=1 do?
Some people commented on the project and said it could be replaced by --. I think of it as a bitwise AND operator, but what does it have to do with --?
And next:
How did they use [e.which&3] together with the preset array to filter keystroke "i", "j", "k", "l" too effectively?
I notice the array has the length of 4, which is the length of the keys needs filtering. Also, pressing another key rather than "i", "j", "k", "l" also works. It leads me to believe that the &3 does something in filtering the 4 keys, but I don't know how.
Those are all I have to ask. The short but complicated code really excites me, and I really appreciate any help in understanding the code further.
Sidenote: I didn't actually look at the website, so if I'm covering anything they already have, I'm sorry. I realised there was a link to it halfway through my post.
Here is the code, unminified, with some adjustments.
HTML:
<body id=b>
<canvas id=c></canvas>
</body>
Javascript:
document.body.onkeyup = handleOnKeyUp;
document.body.onload = handleOnLoad;
function handleOnKeyUp(event) {
e = event;
}
function handleOnLoad(event) {
score = 0, n = 150, x = 11325;
context = c.getContext('2d');
context.fillRect(0, 0, n, n);
end = setInterval(function () {
if (typeof e === "undefined") return; // This isn't part of the original code - removes errors before you press a button
// Map key that was pressed to a "direction"
// l(76) i (73) j(74) k(75).
// If you AND those values with 3, you'd get
// l(0), i(1), j(2), k(3)
var oneDimDirs = [1, -n, -1, n];
var dirChoice = oneDimDirs[e.which & 3];
// Now add the chosen "direction" to our position
x += dirChoice;
if (x % n <= 0 || n * n <= x || // out of bounds
!(context[x] ^= 1) // already passed through here
) {
b.innerHTML = "GameOver:" + score;
clearInterval(end);
}
else {
score++;
context.clearRect(x % n,x / n, 1 , 1)
}
}, 9);
}
Generally, the code makes heavy use of a couple of hacks:
It makes heavy use of global variables and the fact that assigning to an undefined variable creates a global.
It also makes use of irrelevant function parameters to set or modify variables(this shortens the code length)
The code uses a one-dimensional representation of a two-dimensional space. Instead of moving you in two directions, x and y, it "flattens" the representation of the two-dimensional space(the gameboard) into a one-dimensional array. x represents your position on the overall game board. If you add 1 to x, you will move along the current "line"(until you get to its end). Adding n moves you a whole line forward, so it's similar to moving once down.
Your questions, one by one:
1) How can they select element with id 'c' without using getElementById() rather than a simple c
Kooilnc's answer already covers this. This is called "named access":
http://www.whatwg.org/specs/web-apps/current-work/#named-access-on-the-window-object
2) Will replacing parameters of a functions by quick assigning variables affect the function at all? If it does, how will it be calculated?
You misunderstood what is happening here. First, functions accept values as their parameters, and expressions produce values when they are evaluated. An assignment expression, n = 150, produces the value 150 when evaluated. As a side effect, it also assigns that value to the variable n. So calling a function func(n = 150) is almost equivalent to func(150), with the exception of that side effect. That side effect is used in the code to save space, instead of having to assign the variables on separate lines.
Now, for the canvas WTF - As far as I can tell, a canvas element's default width and height happen to be 300px and 150px. You cannot draw past those limits, so trying to execute z.fillRect(0, 0, 150, 11325); will not draw past the 150 height limit. The code authors use the fact that 11325 is bigger than 150 and is thus safe to pass as a parameter(the rectangle will still be drawn as 150x150). 11325 happens to be the one-dimensional coordinate of the starting position.
3) What in the world does it mean?
I hope I mostly answered it within the code. The inner part is unpacked and commented, which only leaves this part unexplained:
context[x] ^= 1.
(Note, ^ === XOR)
The idea is that the authors are using the context as an array to store which positions they've already visited. There are three reasons for doing it this way:
One, they want to assign some value to mark that they've passed through here. context[x] is usually undefined, undefined ^ 1 === 1, so they're assigning ones to the positions they pass through.
Next, they want to be able to check if they've passed through there. Coincidentally, 1 ^ 1 === 0, which makes it easy to check. Note what I mentioned about assignment expressions - the value of this assignment expression will be either 1, if the position has not been visited before, or 0, if it has. This allows the authors to use it as a check.
Since the check they use is something like expr & expr & expr, expressions which yield true/false or 1/0 values will work the same way as if it was expr && expr && expr(true and false are converted to the numbers 1 and 0 when used in &)
How did they use [e.which&3] together with the preset array to filter keystroke "i", "j", "k", "l" too effectively?
I hope I answered this sufficiently with comments in the code. Basically, using the onkeyup handler, they store the event which has the key that was pressed. On the next interval tick, they check e.which to determine which direction to go in.
About
1) How can they select element with id 'c' without using getElementById() rather than a simple c
In most browsers you can access an element using its ID as a variable in the global namespace (i.e. window). In other words, to retrieve <div id="c"> you can also use c, or window.c.
See also
The other questions I leave to smarter people ;)
1) How can they select element with id 'c' without using getElementById() rather than a simple c
I believe it was an old version of IE that originally allowed access of DOM elements in JS directly by their id, but a number of other browsers followed for compatibility with websites that rely on this. In general it's not a great thing because you can get weird bugs if you create variables with the same names as the element ids (not that that matters for this example).
2) Will replacing parameters of a functions by quick assigning variables affect the function at all? If it does, how will it be calculated?
You said within your point (2) that z.fillRect(s = 0, 0, n = 150, x = 11325); can be written instead as z.fillRect(0, 0, 150, 11325);, but that is true only in as far as having the function call to fillRect() work the same way. This change would break the overall program because the assignment statements are needed to create and set the n and x global variables.
In a general sense in JS the assignment operator = not only assigns the value from the right-hand operand to the variable on the left, but the whole expression gives the value of the right-hand operand. So someFunc(x = 10) sets the variable x to 10 and passes the value 10 to someFunc().
In the case of that fillRect(), the n and x variables have not previously been declared, so assigning a value to them creates them as globals.
3) What in the world does it mean? &(z[x+=[1,-n,-1,n][e.which&3]]^=1)?
Well, it's (obviously) kind of complicated. To answer the specific questions you mentioned about parts of it:
How did they use [e.which&3] together with the preset array to filter keystroke "i", "j", "k", "l" too effectively?
The keys "i", "j", "k", and "l" are a good choice for up/left/down/right controls in a game because their physical layout on a standard keyboard corresponds to up/left/down/right but also because those letters belong next to each other in the alphabet so they have contiguous keycodes too: 73, 74, 75, 76. So when you take those keycodes and do a bitwise AND with &3 you get the values 1, 2, 3, 0 which then act as appropriate indices into the [1,-n,-1,n] array.
What does ^=1 do? ... I think of it as a bitwise AND operator ...
It's not a bitwise AND operator. ^ is a bitwise XOR, and ^= is the bitwise XOR assignment operator. That is, x ^= 1 is equivalent to x = x ^ 1.

Categories

Resources