I'm trying to understand this function that returns the ordinal numbers when we give it a number.
Unfortunately I couldn't figure out how this is working with the conditional operator, could someone explain it to me?
function getOrdinalNum(n) {
return n + (n > 0 ? ['th', 'st', 'nd', 'rd'][(n > 3 && n < 21) || n % 10 > 3 ? 0 : n % 10] : '');
}
The best way to explain this sort of thing is to break it down into a function with if statements. Take a look at the newFunction it does the same thing that the function getOrdinalNum does:
function getOrdinalNum(n) {
return n + (n > 0 ? ['th', 'st', 'nd', 'rd'][(n > 3 && n < 21) || n % 10 > 3 ? 0 : n % 10] : '');
}
function newFunction(n) {
if (n > 0) {
if ((n > 3 && n < 21) || n % 10 > 3) {
return n + 'th'; // essentially returning ['th', 'st', 'nd', 'rd'][0];
} else {
return n + ['th', 'st', 'nd', 'rd'][n % 10];
}
}
}
for(let i = 1; i < 9; i++) {
console.log(getOrdinalNum(i));
console.log(newFunction(i));
}
Break it down like this:
n +
(
n > 0
? ['th', 'st', 'nd', 'rd']
[
(n > 3 && n < 21) || n % 10 > 3
? 0
: n % 10
]
: ''
);
Here:
JS checks if n > 0. If yes then:
An array is created ['th', 'st', 'nd', 'rd']
The next [] tells us a property accessor will follow
Which property is determined by the ternary operation. Either 0 (which will mean (th) or the result of n & 10
And the result of accessing that property is added whatever n was.
If n is smaller or equal with 0 then whatever n was, an empty string is added to it.
It helps to know the operator precedence in JS. Give it a goooood read and practice some.
Operators (unary, binary, ternary)
The ternary conditional operator is different than most other operators in that it takes 3 operands instead of one or two.
You are used to unary operators like the negative symbol in -5 which takes one operand and makes it a negative value.
There is also the binary concatenation operator + used like 'hello ' + 'world'. Here there are two operands which produce the value 'hello world'.
The ternary conditional operator has the form
/* conditional expression */ ? /* expression if truthy */ : /* expression if not truthy*/
Where the comments are the operands for you to fill in with the more complex code from your example. // if n > 0 then the complex expression, otherwise the empty string
Simple example.
Try to run the following statements in your browser.
console.log(true ? 'true value' : 'false value');
var x = 3 > 1 ? 'true value' : 'false value';
console.log(x);
prompt('try entering a blank space, or characters') ? 'a' : 'b';
The code flows much the same as the other answers describe. The first expression is emitted if the condition is truthy otherwise the second expression is emitted.
Here are some docs on what I mean by truthy
Related
I am trying to wrap my head around recursive functions. I've tried a number of entry level exercises with no success. For example, I put this code into JS fiddle. I intended for it to take the sum of all numbers from 1 to n.
function sumAll(n) {
if (n == 1 ) {
return 1;
} else if (n > 1) {
return sumAll(n--) + n;
}
}
console.log(sumAll(3));
feeding 3 to the function should give me '6'. I get an error, though.
The -- suffix operator will evaluate to the original value of n, and the subtraction from n will happen afterwards (which is also not desired as you still want to do + n). That means the recursive call gets the same value for n as the caller, and so you don't get closer to the end...
Don't use -- here, but -1:
function sumAll(n) {
if (n == 1 ) {
return 1;
}
else if (n > 1) {
return sumAll(n-1) + n;
}
}
console.log(sumAll(3));
Perhaps you will enjoy a repeatable technique that can guide you through designing your recursive function. Let's solve sumAll using inductive reasoning -
If n is zero, return the empty sum, zero
(inductive) n is negative or positive. If n is negative, return the negative result of the subproblem sumAll(-n)
(inductive) n is positive. Return n plus the result of the subproblem sumAll(n - 1)
function sumAll(n) {
if (n == 0) // 1
return 0
else if (n < 0) // 2
return -sumAll(-n)
else
return n + sumAll(n - 1) // 3
}
console.log(sumAll(-10), sumAll(0), sumAll(10))
// -55 0 55
Here is sumAll written using a switch instead. It behaves identically but maybe you will find the syntax nicer to read -
function sumAll(n) {
switch (true) {
case n == 0: return 0 // 1
case n < 0: return -1 * sumAll(-n) // 2
default: return n + sumAll(n - 1) // 3
}
}
console.log(sumAll(-10), sumAll(0), sumAll(10))
// -55 0 55
Here is sumAll again as a pure, functional expression -
const sumAll = (n = 0) =>
n == 0 // 1
? 0
: n < 0 // 2
? -1 * sumAll(-n)
: n + sumAll(n - 1) // 3
console.log(sumAll(-10), sumAll(0), sumAll(10))
// -55 0 55
I have to convert a number to comma format. E.g 12345 => 12,345.
I have my solution :
function convert(n) {
n = n.toString();
var result = '';
var count = 0,
var idx = n.length - 1;
while (r = n[idx]) {
count++;
result = ((count % 3 == 0 && count != n.length) ? ',' : '') + r + result;
idx--;
}
return result;
}
But someone else used :
result = ((count % 3 != 0 || count == n.length) ? '' : ',') + r + result;
They both work but now I am confused about my own solution and just lost why they both work. Ah not sure if my question is clear.
!(x AND y) is equal to !x OR !y
(and you can pull a NOT out of a boolean x by double negation, for example:
x == !!x
so
x AND !y (your original expression) is equivalent to !(!x OR y)
if you remove the negation (!) from the beginning, then you actually get the Negated form and that is why the second and third values of the ternary operator are reversed in your second example.
The two expressions are equivalent, the second one is just the negated version of yours. The opposite (more or less) of == is !=, the opposite of && is ||, and the opposite of true is false.
You are placing a comma whenever the count is divisible by 3 and you aren't at the start of the number. They are not placing a comma anytime the count is not divisible by 3 or they are at the start of the number.
Assume that, count % 3 = 0 and count > n.length
Now your logic:
((count % 3 == 0 && count != n.length) ? ',' : '')
which means True && True which results in True hence the first condition after ? which is "," is selected.
Someone else logic:
((count % 3 != 0 || count == n.length) ? '' : ',')
which means 'False || False' which results in 'False' hence second condition after ? which is "," is selected.
P.S: Both are using similar logic
How to detect if positive or nagative changes ?
Example :
1 change to 2 = false
0 change to 1 = false
Because both are positive numbers
1 change to -1 = true
0 change to -1 = true
Because positive change to negative
-1 change to 0 = true
-1 change to 1 = true
Because negative change to positive
I do like..
var a_test,b_test;
if(a<0) {
a_test = 'negative';
} else {
a_test = 'positive';
}
if(b<0) {
b_test = 'negative';
} else {
b_test = 'positive';
}
if(a_test!==b_test) {
alert('Yeah!');
}
For test : http://jsfiddle.net/e9QPP/
Any better coding for do something like this ?
Wiki : A negative number is a real number that is less than zero
According to the Zen of Python,
Readability counts.
So, I present more readable and code-review passing version
if (a < 0 && b >= 0 || a >= 0 && b < 0) {
alert("Yeah");
}
You seem to want
if (a*b<0) alert('Yeah!');
If you want to consider 0 as a positive number, you may use
if (a*b<0 || (!(a*b) && a+b<0)) alert('Yeah!');
Taking a suitable sign function:
function sign(x) {
return typeof x === 'number' ? x ? x < 0 ? -1 : 1 : x === x ? 0 : NaN : NaN;
}
Then your problem can be expressed in clear and (hopefully) simple terms:
if (sign(a) !== sign(b)) {
// Your code here
}
Based on your criteria, it seems you simply want to compare the signs of the two numbers. The sign is stored in the highest bit of the number, therefore, to compare the signs, we can simply shift all the other bits off the number, and compare the signs.
Numbers in JavaScript are 64 bit (double), so we need to shift off the 63 bits preceding the sign:
if (a >>> 63 !== b >>> 63) alert('Yeah!');
Here is a jsFiddle demo
Here is a jsPerf comparison based on the 4 methods offered here.
Please note that this assumes that the numbers are 64 bit. I don't know if the spec restricts it to 64-bit, but it's plausible that there are browsers out there (or will be one day) where numbers are represented by perhaps a 128-bit number or greater.
Maybe a bit late, but I had the same problem.
Assuming you now that a and b are numbers why not:
if(a < 0 ? b >=0 : b < 0){
// your code here
}
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I have the following code:
c.m & 3 || (b |= 2,
65 <= a && 90 >= a ? a = 65
: 48 <= a && 57 >= a ? a = 48
: b & 1 ? 97 <= a && 122 >= a ? a = 65
: 197 == a || 229 == a ? b &= 5
: 192 <= a && 687 >= a ? a = 192
: 1536 <= a ? a = 1536
: 912 <= a ? a = 912
: 160 <= a ? a = 160
: 127 <= a ? b &= 5
: 33 <= a ? a = 59
: b &= 5
: 48 > a ? b &= 5
: 65 > a ? a = 59
: 96 > a ? b &= 5
: 112 > a ? a = 96
: 187 > a ? b &= 5
: a = 59);
I'm confused even where to start. Is || a binary operator? why is there a comma at beginning? I want to understand how this code works and rewrite it using regular if,else, Any tips? Thanks!
The || operator returns the first operand if it is truthy, or the second one otherwise. && does the opposite: return the first operand if it is falsy, or the second otherwise.
a ? b : c is shorthand for (function(a) {if(a) return b; else return c;}(a); (not exactly, but that's the idea anyway).
The , operator evaluates both its operands and returns the second.
With all that in mind, the code above becomes:
if( !(k & 3)) {
b |= 2;
if( 65 <= a && 90 >= a)
a = 65;
else if( 48 <= a && 57 >= a)
a = 48;
else if( b & 1) {
if( 97 <= a && 122 >= a)
a = 65;
else if( 197 == a || 229 == a)
b &= 5;
else if( 192 <= a && 687 >= a)
a = 192;
else if( 1536 <= a)
a = 1536;
else if( 912 <= a)
a = 912;
else if( 160 <= a)
a = 106;
else if( 127 <= a)
b &= 5;
else if( 33 <= 1)
a = 59;
else
b &= 5;
}
else if( 48 > a)
b &= 5;
else if( 65 > a)
a = 59;
else if( 96 > a)
b &= 5;
else if( 112 > a)
a = 96;
else if( 187 > a)
b &= 5;
else
a = 59;
}
I can't tell you what it means, though. It's just a bunch of numbers being checked. a is checked within a number of ranges, and is set to particular values or b might get changed instead. It's a huge mess to me, it needs context to make sense.
Double pipe means OR and double ampersand means AND.
Also, the ?: syntax is a shortcut for if/else.
So
if (a == 3) alert('a is 3')
else alert('a is NOT 3')
can be written like
a == 3 ? alert('a is 3') : alert('a is NOT 3');
or
alert(a == 3 ? 'a is 3' : 'a is NOT 3')
As with single pipe and ampersand signs (that can be combined with some other query operators such as equals - =), they are bitwise operators and they don't deal with straight forward conditions such as if (a == 3) etc. that return a boolean value.
Something to note is, double pipe can also be used when checking if a value is undefined. So it apparently casts the type into a boolean. Here's an example.
// note that val is not defined yet
var val = num || 0;
// so val will be assigned 0. same as:
if (typeof num == 'undefined') val = 0;
else val = num;
This code is terrible, there's no other word. It seems to be the result of some obfuscater. I understand you want to know how this code works, but the whole point of obfuscated code is that it's either impossible or extremely hard to work it out.However, knowing what all the operators are, and what they do, is the best place to start, IMO. A full reference of the various kinds of operators is to be found here, on MDN
First off: the Bitwise operartors:
k & 3 will return either 0, 1 or 3. Why? because & returns a series of bits that both the left and right operand "share"Consider the following:
| integer | binary |
====================
| 1 | 0001 |
| 2 | 0010 |
| 3 | 0011 |
| 4 | 0100 |
--------------------
Then it stands to reason that 1 & 3 equals 1, because only the first bit is "on" in both operands (000>1< & 001>1<).
Another bitwise operator that your snippet uses is the single pipe: |, in an expression like b |= 2. Keeping the above table in mind: 1 | 2 resolves in 3, 1 | 3 returns 3. This is the bitwise OR: set each bit to 1 if either of the two operands have it set to 1. In the case b |= 2 the resulting value is assigned to b, that's what the assignment operator is for, so if b is 1, b will be set to 3, if b is 2 or 3, nothing is changed and so on.
Other than that, you have a bunch of nested ternary's (x ? a : b) which, when written in full is the same as:
if (x)//truthy
{
a;
}
else
{
b;
}
Lastly, what threw you the most apparently is that logical operator k & 3 ||... in the begining. The || is just a logical or. Depending on the resulting value of the left operand, either that left operand or the right operand is used. Again, it's short for:
if (k & 3)
{//will be true if either the first, second or both the second and first bits are set on k
k & 3;
}
else
{//if k is 4, for example
all the other stuff
}
Just take some time browsing through the MDN reference and get to know the various operators. Once you've gotten to know them, it's like finding out about regex: a vast, exciting realm of possibilities unfolds, things that took many, many lines of code before suddenly can be written using just one operator.
how to convert -1 to 1 with javascript ?
var count = -1; //or any other number -2 -3 -4 -5 ...
or
var count = 1; //or any other number 2 3 4 5 ...
result should be
var count = 1; //or any other number 2 3 4 5 ...
count = Math.abs(count)
// will give you the positive value of any negative number
The abs function turns all numbers positive: i.e Math.abs( -1 ) = 1
Alternative approach (might be faster then Math.abs, untested):
count = -5;
alert((count ^ (count >> 31)) - (count >> 31));
Note that bitwise operations in javascript are always in 32-bit.
If the number of interest is input... In addition to Math.abs(input)....
var count = (input < 0 ? -input : input);
jsFiddle example
(edit: as Some pointed out -input is faster than -1 * input)
The above makes use of the Javascript conditional operator. This is the only ternary (taking three operands) Javascript operator.
The syntax is:
condition ? expr1 : expr2
If the condition is true, expr1 is evaluated, if it's fales expr2 is evaluated.