JavaScript: Is the `if / else` statement faster than the conditional statement in? - javascript

Consider the following two pieces of code:
var adj=0>grip.y?0<grip.x?0:-180:0<grip.x?-360:-180;
and
var adj;
if (grip.y < 0) {
if (grip.x > 0)
adj = 0;
else
adj = -180;
}
else {
if (grip.x > 0)
adj = -360;
else
adj = -180;
}
They both produce the same result, but which is faster?

The speed difference will be negligible - use whichever you find is more convinient and readable. There wont be any problem with the wrong conditional construct.

Use switch conditions,that is faster than if and other conditional statements.

Just to check the performance in JavaScript, I tried to do a small experiment.
console.time("ternary operator");
const val = (5 > 2) ? true : false;
console.log(val);
console.timeEnd("ternary operator");
console.time("if condition");
let val2;
if (5 > 2) {
val2 = true;
} else {
val2 = false;
}
console.log(val2)
console.timeEnd("if condition");
and the output is quite shocking as the if condition is almost twice faster than the ternary statements.
Results :-
So to conclude I would suggest using the if condition over the ternary operator.

Related

Assigning a variable = to any number between these two numbers

is there any way of assigning a variable lets say,
var between = any number between 5 and 10?
So when I call something like,
if(between === 6){
//do this
}
it ends up being true and running the code?
You would use two parts to a comparison. There is no single operand in Javascript that checks for "betweenness". You could build your own function to do that if you wanted. Here's an if statement that requires two conditions to be true before the statement is true:
if (val >= 5 && val <= 10) {
// val is between 5 and 10 (including both 5 and 10)
}
Or, you could build yourself a little function:
function isBetween(val, min, max) {
return val >= min && val <= max;
}
if (isBetween(val, 5, 10)) {
// val is between the two numbers
}
If you prefer jQuery and have between numbers in the array, one of the way to solve this kind of task is by using jQuery.inArray().
for example:
var between = [5,6,7,8,9,10];
if($.inArray(6, between)) {
// do somethings
}

Advice on how to code Luhn Credit Card validation with Javascript?

I'm pretty awful at Javascript as I've just started learning.
I'm doing a Luhn check for a 16-digit credit card.
It's driving me nuts and I'd just appreciate if someone looked over it and could give me some help.
<script>
var creditNum;
var valid = new Boolean(true);
creditNum = prompt("Enter your credit card number: ");
if((creditNum==null)||(creditNum=="")){
valid = false;
alert("Invalid Number!\nThere was no input.");
}else if(creditNum.length!=16){
valid = false;
alert("Invalid Number!\nThe number is the wrong length.");
}
//Luhn check
var c;
var digitOne;
var digitTwo;
var numSum;
for(i=0;i<16;i+2){
c = creditNum.slice(i,i+1);
if(c.length==2){
digitOne = c.slice(0,1);
digitTwo = c.slice(1,2);
numSum = numSum + (digitOne + digitTwo);
}else{
numSum = numSum + c;
}
}
if((numSum%10)!=0){
alert("Invalid Number!");
}else{
alert("Credit Card Accepted!");
}
</script>
The immediate problem in your code is your for loop. i+2 is not a proper third term. From the context, you're looking for i = i + 2, which you can write in shorthand as i += 2.
It seems your algorithm is "take the 16 digits, turn them into 8 pairs, add them together, and see if the sum is divisible by 10". If that's the case, you can massively simplify your loop - you never need to look at the tens' place, just the units' place.
Your loop could look like this and do the same thing:
for (i = 1; i < 16; i +=2) {
numSum += +creditNum[i];
}
Also, note that as long as you're dealing with a string, you don't need to slice anything at all - just use array notation to get each character.
I added a + in front of creditNum. One of the issues with javascript is that it will treat a string as a string, so if you have string "1" and string "3" and add them, you'll concatenate and get "13" instead of 4. The plus sign forces the string to be a number, so you'll get the right result.
The third term of the loop is the only blatant bug I see. I don't actually know the Luhn algorithm, so inferred the rest from the context of your code.
EDIT
Well, it would have helped if you had posted what the Luhn algorithm is. Chances are, if you can at least articulate it, you can help us help you code it.
Here's what you want.
// Luhn check
function luhnCheck(sixteenDigitString) {
var numSum = 0;
var value;
for (var i = 0; i < 16; ++i) {
if (i % 2 == 0) {
value = 2 * sixteenDigitString[i];
if (value >= 10) {
value = (Math.floor(value / 10) + value % 10);
}
} else {
value = +sixteenDigitString[i];
}
numSum += value;
}
return (numSum % 10 == 0);
}
alert(luhnCheck("4111111111111111"));
What this does is go through all the numbers, keeping the even indices as they are, but doubling the odd ones. If the doubling is more than nine, the values of the two digits are added together, as per the algorithm stated in wikipedia.
FIDDLE
Note: the number I tested with isn't my credit card number, but it's a well known number you can use that's known to pass a properly coded Luhn verification.
My below solution will work on AmEx also. I submitted it for a code test a while ago. Hope it helps :)
function validateCard(num){
var oddSum = 0;
var evenSum = 0;
var numToString = num.toString().split("");
for(var i = 0; i < numToString.length; i++){
if(i % 2 === 0){
if(numToString[i] * 2 >= 10){
evenSum += ((numToString[i] * 2) - 9 );
} else {
evenSum += numToString[i] * 2;
}
} else {
oddSum += parseInt(numToString[i]);
}
}
return (oddSum + evenSum) % 10 === 0;
}
console.log(validateCard(41111111111111111));
Enjoy - Mitch from https://spangle.com.au
#Spangle, when you're using even and odd here, you're already considering that index 0 is even? So you're doubling the digits at index 0, 2 and so on and not the second position, fourth and so on.. Is that intentional? It's returning inconsistent validations for some cards here compared with another algorithm I'm using. Try for example AmEx's 378282246310005.

What does var prime = num != 1; mean?

I know this is similar to another SO question, but the variable prime is supposed to be any number other than 1, and it looks to me like it would be assigned the boolean value of num != 1. Can anyone tell me what this line of code is actually doing?
Here's the code where it's being used
function isPrime( num ) {
var prime = num != 1; // Everything but 1 can be prime
for ( var i = 2; i < num; i++ ) {
if ( num % i == 0 ) {
prime = false;
break;
}
}
return prime;
}
EDIT:
I assume that this line does something like this:
if( num != 1) {
prime = num;
}
But I still want to know why or how this line of code does this.
As you were thinking correctly, the statement var prime = num != 1; assigns the result of the boolean expression (num != 1) to the variable prime. This special case is included in kind of every prime checking code because 1 itself is not a prime number.
Your algorithm could be even faster if you only checked for divisors up to the square root of the input value. You can read about this here and may notice that it's far more efficient to check if num > i*i than sqrt(num) > i.
Additionally the algorithm you have could still return wrong values if you feed it negative or zero values.
In other words:
If num == 1, set prime to false and skip the loop.
Otherwise, enter the loop and use the standard logic to determine the value of prime.
This is done because the standard logic (inside the loop) will not work on the number 1.
Therefore, as pst says, you check for the edge case outside the loop.
This helps keep the logic clean inside the loop.
To make it more readable (and correct for all values) I would re-write it like this:
function isPrime( num ) {
if (num <= 1) {
return false;
}
for ( var i = 2; i < num; i++ ) {
if ( num % i == 0 ) {
return false;
}
}
return true;
}
You could also exit the loop once i is greater than num / 2 to make it more efficient.
1 is not a prime number
That is an edge-case check because for(i = 2;..) (below) "skips" 1: because the loop never runs, prime is only set once to false (which is the evaluation of i != 1, when i = 1).
However, I find it confusing and would have used:
if (i <= 1) {
return false;
} else {
// other stuff
}
The point of that line of code is to achieve two goals in one:
Firstly, they need to create a boolean variable
Second, they need to check if the number is 1, then it's not prime
They are just doing both at the same time.

JS Variable is outputting as isNaN when I need a number

Here is the assignment so it's clear what I'm trying to do.
Write a program that calculates the price of a hotel room based on three factors. First, how many will be in one room: 1-2, 3-4, or 5-6? No more than six are allowed in a room. Second, are the guests members of AAA? Third, do they want a room with a view? The rate is calculated as follows:
Basic room rate is:
1-2 people = $50/night
3-4 people = $60/night
5-6 people = $70/night
There is a discount for AAA members off of the basic room rate per night:
1-2 people = 15%
3-4 people = 10%
5-6 people = 5%
A room with a view costs 10% more per night after all other calculations are performed.
The program should prompt the user for all the inputs, perform the calculations and output the total cost per night. It is suggested to use at least some nested if/else structures to calculate the cost.
Debuggers like firebug and JSLint haven't been any help and I suspect I'm just doing something completely wrong, though I haven't had trouble with "nested if" logic assignments before. Regardless I am a complete and utter newby.
When I test by inputting 1 for numberOfGuests, N for tripleAStatus, and N for roomView, finalRate is returning as isNaN (I know this means not a number), and I can't figure out why.
//Variable Declaration
var numberOfPeople;
var tripleAStatus;
var roomView;
var discountRate;
var roomRate;
var finalRate;
var discountPercent;
//Input
numberOfPeople = prompt("How many guests will their be? 6 Maximum.");
tripleAStatus = prompt("Are you a AAA Member? Y/N.");
roomView = prompt("Would you like your room to have a view?");
//Logic
if ((numberOfPeople <= 2) && (numberOfPeople > 0)) {
roomRate = 50;
discountPercent = .15;
} else if ((numberOfPeople <= 4) && (numberOfPeople > 2)) {
roomRate = 60;
discountPercent = .10;
} else if ((numberOfPeople <= 5) && (numberOfPeople > 4)) {
roomRate = 70;
discountPercent = .5;
} else {
alert("Your number of guests must be at least 1 and no more than 6");
}
if (tripleAStatus = "Y") {
discountRate = roomRate - (roomRate * discountRate);
} else if (tripleAStatus = "N") {
discountRate = roomRate;
} else {
alert("You need to answer with either Y or N");
}
if (roomView = "Y") {
finalRate = (discountRate) + ((discountRate) * .10);
} else if (roomView = "N") {
finalRate = discountRate;
} else {
alert("You need to answer with either Y or N");
}
//Output
document.write("Total cost per night is " + "$" + finalRate);
It looks like
discountRate = roomRate - (roomRate * discountRate);
Should read
discountRate = roomRate - (roomRate * discountPercent);
Which is why you're getting NaN in finalRate; discountRate hasn't been defined at this point, so your code actually reads discountRate = 1 - (1 * undefined).
As other posters have mentioned, you also need to change your conditionals to use == or ===; = is an assignment operator, so rather than checking if tripleAStatus is "Y", you're actually checking if "Y" evaluates to true (which it always will).
tripleAStatus = 'N';
if (tripleAStatus = 'Y') {
// tripleAStatus is now "Y", and the code inside this if will always be executed
}
Working changes: http://jsfiddle.net/5ZVkE/
In your If statements, you are assigning values by using single "=". Since the assignment always occurs, it will return true. In order to compare values, you need to use double "==" in the if statement. like this:
if (tripleAStatus == "Y") {
discountRate = roomRate - (roomRate * discountRate);
} else if (tripleAStatus == "N") {
discountRate = roomRate;
} else {
alert("You need to answer with either Y or N");
}
Replace the single '=' in your 'if' statements with '=='. You're currently using assignment operators instead of equality.
e.g.:
if (tripleAStatus == "Y") ...
You are using assignments instead of equality operators in your if statements. i.e. change
if (tripleAStatus = "Y")
to
if (tripleAStatus == "Y")
Please use ===!! this way, the type in the statement isn't casted and therefor more strictly checked if its the same type.
if (tripleAStatus === "Y") {
discountRate = roomRate - roomRate * discountRate;
} else if (tripleAStatus === "N") {
discountRate = roomRate;
}
/e -> & its faster!
prompt() returns a STRING not a NUMBER.
Use parseInt() with numberOfPeople.
And the other problem, you copied and pasted the wrong variable names in your formulas. Look at how you are using discountRate instead of discountPercent.

Problem with JavaScript arithmetic

I have a form for my customers to add budget projections. A prominent user wants to be able to show dollar values in either dollars, Kila-dollars or Mega-dollars.
I'm trying to achieve this with a group of radio buttons that call the following JavaScript function, but am having problems with rounding that make the results look pretty crummy.
Any advice would be much appreciated!
Lynn
function setDollars(new_mode)
{
var factor;
var myfield;
var myval;
var cur_mode = document.proj_form.cur_dollars.value;
if(cur_mode == new_mode)
{
return;
}
else if((cur_mode == 'd')&&(new_mode == 'kd'))
{
factor = "0.001";
}
else if((cur_mode == 'd')&&(new_mode == 'md'))
{
factor = "0.000001";
}
else if((cur_mode == 'kd')&&(new_mode == 'd'))
{
factor = "1000";
}
else if((cur_mode == 'kd')&&(new_mode == 'md'))
{
factor = "0.001";
}
else if((cur_mode == 'md')&&(new_mode == 'kd'))
{
factor = "1000";
}
else if((cur_mode == 'md')&&(new_mode == 'd'))
{
factor = "1000000";
}
document.proj_form.cur_dollars.value = new_mode;
var cur_idx = document.proj_form.cur_idx.value;
var available_slots = 13 - cur_idx;
var td_name;
var cell;
var new_value;
//Adjust dollar values for projections
for(i=1;i<13;i++)
{
var myfield = eval('document.proj_form.proj_'+i);
if(myfield.value == '')
{
myfield.value = 0;
}
var myval = parseFloat(myfield.value) * parseFloat(factor);
myfield.value = myval;
if(i < cur_idx)
{
document.getElementById("actual_"+i).innerHTML = myval;
}
}
First of all, Don't set myfield.value = myval after doing the math. You'll accumulate rounding errors with each additional selection of one of the radio buttons. Keep myfield.value as dollars all the time, then calculate a display value. This will also reduce the number of cases in your if-else cascade, as you will always be converting from dollars.
Now calculate by division -- you'll never have to multiply by 0.001 or 1000 since you're always converting in the same direction.
Use Math.round() to control rounding errors. You can multiply your original value first, then divide by a larger factor to also help control rounding errors; e.g. both these are the same in pure mathematics:
newvalue = value / 1000;
newvalue = (value * 10) / 10000;
Added
switch (new_mode)
{
case 'd':
divisor = 1;
break;
case 'kd':
divisor = 1000;
break;
case 'md':
divisor = 1000000;
break;
}
var displayValue = myfield.value / divisor;
Also, don't assign a string of numbers divisor = "1000"; use actual numbers divisor = 1000 (without the quotes)
Javascript's floating point numbers are a constant source of irritation.
You should try adding toFixed() to reduce the inevitable absurd decimals, and I've actually had to resort to forcing it to do it's rounding down where I don't care about it by doing something like:
number_to_be_rounded = Math.round(number_to_be_rounded*1000)/1000;
number_to_be_rounded = parseFloat(number_to_be_rounded.toFixed(2));
It's ugly, but it's close enough for a non-financial system.

Categories

Resources