Compare undefined/null/NaN with number in ActionScript - javascript

In ActionScript 1 and 2, if you compare undefined, null or NaN with an arbitrary number using >= or <= operator, the result is always true. Test code:
var x, n, range = 1000;
for (var i = 0; i < 3; ++i) {
switch (i) {
case 0:
x = undefined;
break;
case 1:
x = null;
break;
case 2:
x = NaN;
break;
}
n = range*Math.random();
trace(x + ' >= ' + n + ': ' + (x >= n));
n = range*Math.random();
trace(x + ' <= ' + n + ': ' + (x <= n));
}
Furthermore, isNaN(null) return true.
These are contrary to JavaScript and may not conform with ECMA standard.
Are these bugs or intention?
Thanks!

Since ActionScript 2 knows only one numerical type, Number, all the non-numerical elements in your comparisons are cast to Number - which would be the same as writing:
Number (null) <= n
Number (undefined) <= n
Number (NaN) <= n
Number ({anything but a number}) always returns NaN, therefore all your statements really only compare random Numbers with NaN. The ActionScript documentation clearly warns about NaN not being comparable, and advises to always use isNaN() to test for it.
If you do compare with NaN, however, it is a strange thing in AS2:
NaN == Number // returns false
NaN != Number // returns true
These behave as expected, but:
NaN >= Number // returns true
NaN <= Number // returns true
and finally:
NaN > Number // returns undefined
NaN < Number // returns undefined
Of course that is not very intuitive - any comparison with NaN should always be false, and that has been fixed in AS 3 - but it makes absolute sense that null is not a Number, and hence isNaN(null) should return true.

Related

String to integer leetcode

I was doing following leetcode question
Implement atoi which converts a string to an integer.
The function first discards as many whitespace characters as necessary
until the first non-whitespace character is found. Then, starting from
this character, takes an optional initial plus or minus sign followed
by as many numerical digits as possible, and interprets them as a
numerical value.
The string can contain additional characters after those that form the
integral number, which are ignored and have no effect on the behavior
of this function.
If the first sequence of non-whitespace characters in str is not a
valid integral number, or if no such sequence exists because either
str is empty or it contains only whitespace characters, no conversion
is performed.
If no valid conversion could be performed, a zero value is returned.
Note:
Only the space character ' ' is considered as whitespace character.
Assume we are dealing with an environment which could only store
integers within the 32-bit signed integer range: [−231, 231 − 1]. If
the numerical value is out of the range of representable values,
INT_MAX (231 − 1) or INT_MIN (−231) is returned.
Question link: https://leetcode.com/problems/string-to-integer-atoi/
Here for this input "-91283472332", I am not sure why do they expect the following output -2147483648 instead of -91283472332
Not sure, If this relevant but this is my code
/**
* #param {string} str
* #return {number}
*/
var myAtoi = function(str) {
let i = 0
let output = ''
let nonWhiteCharacter = false
while (i<str.length) {
const char = str[i]
if (!char == " ") {
if (char.toLowerCase() === char.toUpperCase()) {
if (!nonWhiteCharacter) nonWhiteCharacter = true
output = output + char
}
if (!nonWhiteCharacter) return 0
}
i++
}
return output === null ? 0 : parseInt(output)
}
I am not sure why do they expect the following output -2147483648 instead of -91283472332
Because:
Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [−231, 231 − 1]. If the numerical value is out of the range of representable values, INT_MAX (231 − 1) or INT_MIN (−231) is returned.
So if the extracted number is larger than 2 ** 31 - 1, the returned number should be 2 ** 31 - 1 instead.
Similarly, if the extracted number is smaller than -(2 ** 31), instead return -(2 ** 31).
This would probably be easier with a regular expression:
const myAtoi = (str) => {
const match = str.match(/^ *([+-]?\d+)/);
if (!match) return;
const num = Number(match[1]);
return Math.max(
Math.min(2 ** 31 - 1, num),
-(2 ** 31)
);
};
console.log(
myAtoi(' 123'),
myAtoi('-456'),
myAtoi('-9999999999999'),
myAtoi('9999999999999')
);
Have a look it this solution. As we are dealing with integers, they only hold 32-bit. 2^31 < x <= -2^31. So here we use a try catch as the 32bit integer can raise NumberFormat Exception which will be caught by the catch block.
class Solution {
public int myAtoi(String str) {
int flag=0, sign = 0;
int n = str.length();
StringBuilder st = new StringBuilder();
int i =0;
//clear white spaces
while(i<n && str.charAt(i) == ' '){
++i;
}
//overflow of string
if (i>=n){
return 0;
}
//checking sign and not allowing more than one sign, will return 0 if there is ++,+-,--
while(i<n && (str.charAt(i) == '+' || str.charAt(i) == '-')){
if (sign >= 1){
return 0;
}
else{
st.append((str.charAt(i++) == '+') ? '+': '-');
sign++;
}
}
//checking if character is digit
while(i<n && Character.isDigit(str.charAt(i))){
st.append(str.charAt(i++));
flag = 1;
}
//return 0 if no digits
if(flag == 0)
return 0;
//to check if the number is within the int range
try{
return Integer.parseInt(st.toString());
}
catch(NumberFormatException e){
return (st.charAt(0) == '-') ? Integer.MIN_VALUE : Integer.MAX_VALUE;
}
}
}

Javascript check if a decimal is negative

How would i check if a decimal is negative? Because the if statement automatically turns it into a number...
Example:
var x = -0.24324;
how would i parse it so it tells me x is negative/positive?
Thanks
Edit: Maybe i phrased it badly, the variable changes so something it will be positive like 0.00000001, sometimes -0.0003423423, sometimes 0.0000000234
If i put it in a if statement everything is automatically turned into 0 right? And i can't use a parseFloat in the if statement?
Just check if x less than zero since it's a number:
if (x < 0) {
// it's negative
}
You can use isNaN() function to check whether it is valid number or not.
If it is, then you can check for positive or negative value.
Something like this:
var x = "-123"
var y = -456;
var z = '-123a';
if(!isNaN(x) && x < 0) {
console.log(x + ' is negative');
}
if(!isNaN(y) && y < 0) {
console.log(y + ' is negative');
}
if(!isNaN(z) && z < 0) {
console.log(z + ' is negative');
}
const num = -8;
// Old Way
num === 0 ? num : (num > 0 ? 1 : -1); // -1
// ✅ ES6 Way
Math.sign(num); // -1

What is the best way to determine if a given number is a power of two?

Is there a more effective way to return true if n is a power of two or false if not?
function isPowerOfTwo(n) {
return Math.pow(2, Math.round(Math.log(n) / Math.log(2)));
}
You can actually use ECMAScript5 Math.log:
function powerOfTwo(x) {
return (Math.log(x)/Math.log(2)) % 1 === 0;
}
Remember, in math, to get a logarithm with an arbitrary base, you can just divide log10 of the operand (x in this case) by log10 of the base. And then to see if the number is a regular integer (and not a floating point), just check if the remainder is 0 by using the modulus % operator.
In ECMAScript6 you can do something like this:
function powerOfTwo(x) {
return Math.log2(x) % 1 === 0;
}
See the MDN docs for Math.log2.
Source: Bit twiddling Hacks,
function powerOf2(v) {
return v && !(v & (v - 1));
}
You just bitwise AND the previous number with the current number. If the result is falsy, then it is a power of 2.
The explanation is in this answer.
Note:
This will not be 100% true for programming, mathematical, [also read 'interviewing']. Some edge cases not handled by this are decimals (0.1, 0.2, 0.8…) or zero values (0, 0.0, …)
Using bitwise operators, this is by far the best way in terms of efficiency and cleanliness of your code:
function PowerofTwo(n){
return ((x != 0) && !(x & (x - 1)));
}
what it does is checks the bits that make up the number, i.e. 8 looks like this:
1 0 0 0
x-1 or 7 in this case looks like this
0 1 1 1
when the bitwise operator & is used it invokes an && on each bit of the number (thus 1 & 1 = 1, 1 & 0 = 0, 0 & 1 = 0, 0 & 0 = 1):
1 0 0 0
-0 1 1 1
=========
0 0 0 0
since the number turns into an exact 0 (or false when evaluted as a boolean) using the ! flag will return the correct answer
if you were to do this with a number like 7 it would look like this:
0 1 1 1
-0 1 1 0
=========
1 1 1 0
returning a number greater than zero causing the ! flag to take over and give the correct answer.
A number is a power of 2 if and only if log base 2 of that number is whole. The function below computes whether or not that is true:
function powerOfTwo(n){
// Compute log base 2 of n using a quotient of natural logs
var log_n = Math.log(n)/Math.log(2);
// Round off any decimal component
var log_n_floor = Math.floor(log_n);
// The function returns true if and only if log_n is a whole number
return log_n - log_n_floor == 0;
}
Making use of ES6's Math.clz32(n) to count leading zeros of a 32-bit integer from 1 to 2³² - 1:
function isPowerOf2(n) {
return Math.clz32(n) < Math.clz32(n - 1);
}
/**
* #param {number} n
* #return {boolean}
*/
const isPowerOfTwo = function(n) {
if(n == 0) return false;
while(n % 2 == 0){
n = n/2
}
return n === 1
};
function PowerOfTwo(n){
// Exercise for reader: confirm that n is an integer
return (n !== 0) && (n & (n - 1)) === 0;
}
console.log(PowerOfTwo(3))
console.log(PowerOfTwo(4))
This is for a specific online course that requires an answer in a specific way.
Without using libraries and other methods just loops and .push.
you need to create an inner loop using while
it should start with 1
keep multiplying it with 2 until i,j,k or whatever is greater than the current number(array) so it will have to do 2 4 6 8 10 12 14 16 18 until it is greater than the number
then it will go to the outer loop then repeat again until
const numbers = [5, 3, 9, 30];
const smallestPowerOfTwo = arr => {
let results = new Array;
// The 'outer' for loop -
for (let i = 0; i < arr.length; i++) {
number = arr[i];
// The 'inner' while loop
j = 1;
while (j < number) { //starting from 1 then multiplied by 2 then by 2 again untill it is more than the number
j = j * 2;
}
results.push(j);
}
return results
}
console.log(smallestPowerOfTwo(numbers))

Big Integers in Memoized Recursive Fibonacci (Y)

I've written a version of Y that automatically caches old values in a closure using memoization.
var Y = function (f, cache) {
cache = cache || {};
return function (x) {
if (x in cache) return cache[x];
var result = f(function (n) {
return Y(f, cache)(n);
})(x);
return cache[x] = result;
};
};
Now, when almostFibonacci (defined below) is passed into the above function, it returns the value of a large Fibonacci number comfortably.
var almostFibonacci = function (f) {
return function (n) {
return n === '0' || n === '1' ? n : f(n - 1) + f(n - 2);
};
};
However, after a certain value (Number.MAX_SAFE_INTEGER), integers in JavaScript (owing to their IEEE-754 double precision format) are not accurate. So, considering the fact that the only mathematical operations in the Fibonacci function above are addition and subtraction and since operators cannot be overloaded in JavaScript, I wrote naïve implementations of the sum and difference functions (that both use strings to support big integers) which are as follows.
String.prototype.reverse = function () {
return this.split('').reverse().join('');
};
var difference = function (first, second) {
first = first.reverse();
second = second.reverse();
var firstDigit,
secondDigit,
differenceDigits = [],
differenceDigit,
carry = 0,
index = 0;
while (index < first.length || index < second.length || carry !== 0) {
firstDigit = index < first.length ? parseInt(first[index], 10) : 0;
secondDigit = index < second.length ? parseInt(second[index], 10) : 0;
differenceDigit = firstDigit - secondDigit - carry;
differenceDigits.push((differenceDigit + (differenceDigit < 0 ? 10 : 0)).toString());
carry = differenceDigit < 0 ? 1 : 0;
index++;
}
differenceDigits.reverse();
while (differenceDigits[0] === '0') differenceDigits.shift();
return differenceDigits.join('');
};
var sum = function (first, second) {
first = first.reverse();
second = second.reverse();
var firstDigit,
secondDigit,
sumDigits = [],
sumDigit,
carry = 0,
index = 0;
while (index < first.length || index < second.length || carry !== 0) {
firstDigit = index < first.length ? parseInt(first[index], 10) : 0;
secondDigit = index < second.length ? parseInt(second[index], 10) : 0;
sumDigit = firstDigit + secondDigit + carry;
sumDigits.push((sumDigit % 10).toString());
carry = sumDigit > 9 ? 1 : 0;
index++;
}
sumDigits.reverse();
while (sumDigits[0] === '0') sumDigits.shift();
return sumDigits.join('');
};
Now, by themselves, both these functions work perfectly.1
I have now updated the almostFibonacci function to as follows to use the sum function instead of + and the difference function instead of the - operator.
var almostFibonacci = function (f) {
return function (n) {
return n === '0' || n === '1' ? n : sum(f(difference(n, '1')), f(difference(n, '2')));
};
};
As you may have guessed, this does work. It crashes the fiddle in case of even a small number like 10.
Question: What could be wrong? All the functions here work perfectly individually. But in tandem, they seem to fail. Can anyone here help me debug this particularly complex scenario?
1Except an edge case for the difference function. It requires the first argument to be larger than the second.
Now, by themselves, both these functions work perfectly - Except an edge case for the difference function. It requires the first argument to be larger than the second.
And that's the problem. In your fibonacci algorithm you're at some point calculating difference("2", "2"), which needs to yield "0" to work. It does however return the empty string "", which is not tested against as your guard condition for the recursion. When in the next step computing difference("", "1"), the function will fall into an infinite loop.
Solutions:
Fix that edge case (you still won't need to cope with negative numbers)
Don't use strings for the ordinal number, but only for the fibonacci number itself. You hardly will try the compute the (253+1)th fibonacci number, will you? I would assume this to be a significant speed improvement as well.
var fibonacci = Y(function(fib) {
return function(n) {
if (n == 0) return "0";
if (n == 1) return "1";
return sum(fib(n-1), fib(n-2));
};
});
Here is how I solved the problem at hand.
Changes:
I removed the while (differenceDigits[0] === '0') differenceDigits.shift(); statement. Even though this outputs differences without truncated leading zeros, it outputs a '0' in case of an edge case like difference('2', '2').
I edited the return statement in the almostFibonacci function to return n == 0 || n == 1 ? n : sum(f(difference(n, '1')), f(difference(n, '2')));. Notice that I'm checking for 0 and not '0' with a non strict equality operator.1
1The reason I'm doing n == 0 as opposed to n === '0' is because in JavaScript, '00000' == 0 but '00000' !== '0' and in my new updated difference function, without truncated leading zeros, I can't guarantee the number of zeros for a zero output. Well, actually I can. There would be as many zeros as the length of n.
100th Fibonacci - JSFiddle

What does shorthand "index >= 0 && count++" do?

I was killing time reading the underscore.string functions, when I found this weird shorthand:
function count (str, substr) {
var count = 0, index;
for (var i = 0; i < str.length;) {
index = str.indexOf(substr, i);
index >= 0 && count++; //what is this line doing?
i = i + (index >= 0 ? index : 0) + substr.length;
}
return count;
}
Legal: Think twice before using the function above without giving credit to underscore.string
I put the line alone here, so you don't waste time finding it:
index >= 0 && count++;
I have never seen anything similar to that. I am clueless in what is doing.
index >= 0 && count++;
First part: index >= 0
returns true if index has a value that is greater than or equal to 0.
Second part: a && b
most C-style languages shortcut the boolean || and && operators.
For an || operation, you only need to know that the first operand is true and the entire operation will return true.
For an && operation, you only need to know that the first operand is false and the entire operation will return false.
Third Part: count++
count++ is equivalent to count += 1 is equivalent to count = count + 1
All together now
If the first operand (index >= 0) of the line evaluates as true, the second operand (count++) will evaluate, so it's equivalent to:
if (index >= 0) {
count = count + 1;
}
JavaScript nuances
JavaScript is different from other C-style languages in that it has the concept of truthy and falsey values. If a value evaluates to false, 0, NaN, "", null, or undefined, it is falsey; all other values are truthy.
|| and && operators in JavaScript don't return boolean values, they return the last executed operand.
2 || 1 will return 2 because the first operand returned a truthy value, true or anything else will always return true, so no more of the operation needs to execute. Alternatively, null && 100 will return null because the first operand returned a falsey value.
It's equivalent to:
if (index >= 0) {
count = count + 1;
}
&& is the logical AND operator. If index >= 0 is true, then the right part is also evaluated, which increases count by one.
If index >= 0 is false, the right part is not evaluated, so count is not changed.
Also, the && is slightly faster than the if method, as seen in this JSPerf.
It's the same as:
if(index >= 0){
count++;
}
JavaScript will evaluate the left side (index >= 0), if it's false the && (AND) will short circuit (since false AND anything is false), thus not running `count++.
If it's (index >= 0) true, it evaluates the right side (count++), then it just ignores the output.

Categories

Resources