functions result is NaN - javascript

I am really new in coding therefore I am coding currently a Taximeter. Unfortunately is the result of my code when executing NaN in the console. I tried some ways to rectify my problem but those attempts did not work. I think that some variables are not in the right scope but I do not know how to fix that.
function Taximeter() {
const y = 3.9;
const km = prompt("How far is your target");
if (km <= 7) {
var routePrice = 2.3;
} else if (km > 7) {
let routePrice = 1.65;
var subtractedLength = (km -= 7);
var partialExpenses = (subtractedLength *= routePrice);
var tosevenExpenses = 7 * 2.3;
var combinedExpenses = (tosevenExpenses += partialExpenses);
}
const persons = prompt("How much persons are driving with you?");
if (persons > 8) {
console.log("Only 8 persons can drive with you.");
} else if (8 >= persons >= 5) {
var personsExpenses = 5;
} else if (0 >= persons >= 4) {
personExpenses = 0;
}
if (km <= 7) {
var wholeExpenses = y + km * routePrice + personsExpenses;
} else {
var wholeExpenses = combinedExpenses + y + personsExpenses;
}
console.log(wholeExpenses);
}

It would be helpful to know where exactly NaN is coming up and whether or not you are seeing NaN as the result of an Exception (if an error message was logged to the console) or if NaN is coming up as a result of your own console.log() statements. Part of the issue could be that the function prompt() returns a String, meaning that your variable km is going to be a String and not a Number. Use this line of code instead and it might fix your problem:
const km = parseInt(prompt("How far is your target"));
EDIT:
In response to your comment, there are a couple other issues I see here. There is the issue with your first if and else if clauses where the indentation is a little off. This, as far as I can tell, should not actually affect your code, but it does make it harder to read. Here is how it should look:
if (km <= 7) {
var routePrice = 2.3;
} else if (km > 7) {
let routePrice = 1.65
var subtractedLength = km -= 7;
var partialExpenses = subtractedLength *= routePrice ;
var tosevenExpenses = 7 *2.3;
var combinedExpenses = tosevenExpenses += partialExpenses;
};
Second, in those same if and else if clauses, you use the -=, *=, and += operators when they are unnecessary and may cause errors. I've never seen them used the way that you have before, so I don't know if they actually cause errors, but I would edit those clauses one more time for readability at least:
if (km <= 7) {
var routePrice = 2.3;
} else if (km > 7) {
let routePrice = 1.65
var subtractedLength = km - 7;
var partialExpenses = subtractedLength * routePrice ;
var tosevenExpenses = 7 *2.3;
var combinedExpenses = tosevenExpenses + partialExpenses;
};
Like with km I would also edit your persons declaration to turn that variable into a Number so that the logic operators that you use on it later work properly:
const persons = parseInt(prompt("How much persons are driving with you?"));
Another thing, like a commenter earlier pointed out, 8 >= persons >= 5 will not work the way you think it will - just edit those if and else if clauses like so to fix that error:
if (persons > 8) {
console.log("Only 8 persons can drive with you.");
} else if(persons >= 5 && persons <= 8) {
var personsExpenses = 5;
} else if (persons <= 4 && persons >= 0) {
personExpenses = 0;
};
Finally, your variable declaration of personsExpenses is such that the variable will only be declared if that first else if clause resolves. You need personsExpenses to be declared no matter what, so I would declare it before and outside of any of those conditional clauses:
var personsExpenses
if (persons > 8) {
console.log("Only 8 persons can drive with you.");
} else if(persons >= 5 && persons <= 8) {
personsExpenses = 5;
} else if (persons <= 4 && persons >= 0) {
personExpenses = 0;
};
That's everything that I noticed, so good luck!

Related

What syntax should be used to compare multiple conditions in else if statements?

I am trying to run my code to have a result of "Child" in my console. With the variable patient being 7, I still get the result of "Teenager". Any suggestions?
var patient = 7;
if (patient >= 18) {
ageGroup = 'Adult';
} else if (patient <= 17) {
ageGroup = 'Teenager';
} else if (patient <= 12) {
ageGroup = 'Child';
}
console.log(ageGroup);
The conditions are tested in order. Since both patient <= 17 and patient <= 12 are true, the first one takes precedence, so it says they're a teenager.
When you have overlapping conditions, you can change the order so the more specific one is first. You can also use else instead of testing the last condition.
if (patient >= 18) {
ageGroup = 'Adult';
} else if (patient <= 12) {
ageGroup = 'Child';
} else {
ageGroup = 'Teenager';
}
Another options is to change the conditions so they don't overlap:
if (patient >= 18) {
ageGroup = 'Adult';
} else if (patient >= 13) {
ageGroup = 'Teenager';
} else {
ageGroup = 'Child';
}
Rather than using mnultiple if / else conditions - consider a switch statement - that is literally what it is intended for - to take conditions - compare them and allow code choices.
I also converted the single js codeblock into a function so that you coudl call it from different areas and with different ages.
Note that I am doing the comparison inside the switch statements and then returning true for the matching condition.with the default being that the passed in number is that of an adult.Also the new "let" is better than var since it is now scoped to the function it is in and not cluttering up the global scope.
function checkAge(n) {
let ageGroup;
switch(true) {
case n <= 12:
ageGroup = 'Child';
break;
case n <= 17:
ageGroup = 'Teenager';
break;
default:
ageGroup = 'Adult'
}
return ageGroup;
}
console.log(checkAge(7)); // gives Child
console.log(checkAge(15)); // gives Teenager
console.log(checkAge(29)); // gives Adult
The programming flow defined in your IF-ELSE contains failed in logic structure: The variable with value 7 satisfy the both conditions defined in else if. Then, based in program flow, the console outputs "Teenager" because its the first condition deflected. The code bellow contains an example to resolves this problem:
var patient = 7;
if (patient >= 18) {
ageGroup = 'Adult';
} else if (patient > 12 && patient <= 17) {
ageGroup = 'Teenager';
} else if (patient <= 12) {
ageGroup = 'Child';
}
console.log(ageGroup);
thats because of your conditions have interposition so
you have two ways:
you can resolve this interposition(i suggest this way) :
if (patient >= 18) {
ageGroup = 'Adult';
} else if (patient <= 17 & patient >12) {
ageGroup = 'Teenager';
} else if (patient <= 12) {
ageGroup = 'Child';
}
or
you can change if statment places(i suggest this way if you have to have this interposition):
if (patient >= 18) {
ageGroup = 'Adult';
} else if (patient <= 12) {
ageGroup = 'Child';
} else if (patient <= 17) {
ageGroup = 'Teenager';
}

How can I convert these 'if' statements to an algorithm

I'm trying to convert these 'if' statements to an algorithm, so that I can have many more stages instead of being limited to 10. How would I go about converting it? I just can't wrap my head around the logic!
function getStage(km) {
if (km > 2 && km < 4){
return 1;
}
else if (km > 4 && km < 6){
return 2;
}
else if (km > 6 && km < 8){
return 3;
}
else if (km > 8 && km < 10){
return 4;
}
else if (km > 10 && km < 12){
return 5;
}
else if (km > 12 && km < 14){
return 6;
}
else if (km > 14 && km < 16){
return 7;
}
else if (km > 16 && km < 18){
return 8;
}
else if (km > 18 && km < 20){
return 9;
}
else if (km > 20 && km < 22){
return 10;
}
}
I have tried this:
function getStage(km) {
var tempStage = 0;
for (var i = 0; i < stages; i++) {
var stage = i + 1;
var tempKm = stage * 2;
var nextKm = stage + 2;
if (km > tempKm && km < nextKm) {
tempStage = stage;
}
}
return tempStage;
}
Perhaps I shouldn't be using a for loop? Is there a better way of doing this?
Maybe you are looking for Math.floor
function getStage(km) {
return Math.floor(km / 2)
}
console.log(getStage(2));
// 1
console.log(getStage(10));
// 5
console.log(getStage(11));
// 5
You can just use math to do this. No loops or conditionals necessary.
Notice that your input intervals increase in "steps" of 2, and your outputs increase in "steps" of 1. This makes me think maybe we should divide km by 2.
Since we always want an integer answer, we can use the Math.floor function.
Some examples:
Math.floor(3/2) = 1
Math.floor(4.1/2) = 2
etc.
Depending on what you want to return for edge cases (what if km = 2 or km = 4, or any multiple of 2?) we might be done here. If you wish to return 1 when k=4, 2 when k=6, etc., you'll need to do a little more work.
*** In general: *** if you are working with numbers and you find yourself writing a lot of cases, you can usually use some combination of simple mathematical operators to calculate the result. For problems like these, try thinking about your input/output pairs, and what the relationship is between them.
You could take the floored value of km divided by two plus one.
10 is the upper limit.
function getStage(km) {
return Math.min((km >> 1) + 1, 10);
}
console.log(getStage(2.1)); // 2
console.log(getStage(3)); // 2
console.log(getStage(4)); // 4
Try something like this. This is general solution which applies not only to 2*n series.
const stages = [2, 4, 6, 8, 10, 13, 15, 16, 20]; //should be ordered. Else sort it first.
const getStage = km => stages.indexOf(stages.find(i => km < i));
console.log(getStage(5)); //2
console.log(getStage(1.5)); //0
console.log(getStage(8.1)); //4
console.log(getStage(15)); //7
console.log(getStage(22)); //-1 out of index

Convert huge if else statement into a loop in Javascript

I'm trying to format a number to be displayed in a more friendly way. At the moment, the code is really difficult to update and it's huge and clumsy.
function abb(){
if(m>=1 && m<999){
gold_display = m;
}else if(m>999 && m<999999){
var b = (m / 1000).toFixed(3);
gold_display = b+"k";
}else if (m>999999 && m<999999999){
var b = (m / 1000000).toFixed(3);
gold_display = b+"m";
}else if (m>999999999 && m<999999999999){
var b = (m / 1000000000).toFixed(3);
gold_display = b+"b";
}else if (m>999999999999 && m<99999999999999){
var b = (m / 1000000000000).toFixed(3);
gold_display = b+"t";
}
}
EDIT: THIS WOULD BE THE CODE:
function abb(){
if(m>=1 && m<1000){
gold_display = m;
}else if(m>999 && m<1000000){
var b = (m / 1000).toFixed(3);
gold_display = b+"k";
}else if (m>999999 && m<1000000000){
var b = (m / 1000000).toFixed(3);
gold_display = b+"m";
}else if (m>999999999 && m<1000000000000){
var b = (m / 1000000000).toFixed(3);
gold_display = b+"b";
}else if (m>999999999999 && m<100000000000000){
var b = (m / 1000000000000).toFixed(3);
gold_display = b+"t";
}
}
Yeah it's akward but it was the only solution that came up into my mind, is there a way to convert this into a loop and shrink the code?
I'm thinking in saving the letters "k", "m", "b","t" in an array because I want to go higher to "q", "qi","s", etc.
Thanks and sorry if the question is kinda stupid :(
Count how many times you need to divide by 1000 before you are under 1000
function bigNumber(big) {
let divisor = 1,
steps = 0,
small = big;
while (small >= 1000) {
divisor *= 1000;
small = big / divisor;
++steps;
}
return {steps, divisor, small};
}
let gold = 123456789,
foo = bigNumber(gold);
foo.small.toFixed(3) + ['', 'k', 'm', 'b', 't'][foo.steps];
// "123.457m"
It's not much but one simplification of your code is to eliminate the lower-bound checking since the if/else-if structure will take care of that:
function abb(m) {
if (m < 1) {
// some kind of error?
} else if (m < 1000) {
return m;
} else if (m < 1000000) {
return (m/1000).toFixed(3) + "k";
} else if (m < 1000000000) {
return (m/1000000).toFixed(3) + "m";
} else {
// and so on
}
}
You could do something more clever but I think it is probably best to be simple about it.
But if I understand your code correctly, you're trying to format numbers as thousands ("k"), millions ("m"), billions ("b") etc. Why not look at a library for this such as http://numeraljs.com/?
Specifically, you can use this code:
var numeral = require('numeral').language('en');
to import the numeral.js library, and then this code to perform the formatting:
var str = numeral(12345678).format("0.0a");// "12.3m"
var str = numeral(1234).format("0.0a");// "1.2k"
etc.
Full disclosure: this solution comes with the benefit of no for loop, but it does have some added complexity.
Take the logarithm of m. If 1 <= m< 999 then 0 <= exponent < 3. Similarly, if 1000 <= m < 999999 then 3 <= exponent < 6, and so on. You can see the pattern here, every prefix covers a range of 3 in the logarithmic scale. So you could do something like the following:
function abb(m){
var prefixes = ["","k","m","b","t"];
var log = Math.log10(m);
var prefixRange = parseInt(log/3, 10);
var prefix = prefixes[prefixRange];
return (m / Math.pow(1000, prefixRange)).toFixed(3) + prefix;
}
Actually, in the case of very large numbers, the above will break, so prefixRange = parseInt(log/3, 10) needs to be changed to prefixRange = Math.min(parseInt(log/3, 10), 4),to ensure we don't read beyond the length of array prefixes.
Also, notice that toFixed is not really to be trusted for large numbers in this case. 999999999 / 1000000 gives 1000.000, which I guess is not what you want. Better to round with floor in this case. Since you are only interested in the first digits (3 for the integer and 3 for the decimal part), you can first get those 6 digits and then divide by 1000.
A better function, addressing both issues is:
function abb(m){
var prefixes = ["","k","m","b","t"];
var log = Math.log10(m);
var prefixRange = Math.min(parseInt(log/3, 10), 4);
var prefix = prefixes[prefixRange];
return Math.floor((m / Math.pow(1000, prefixRange - 1)))/1000 + prefix;
}

javascript value coming up empty not sure how to handle it

function updategeneral() {
//tmp = "fine_" + tmp + "_";
var actual = doc.findItem("1speed").value;
var posted = doc.findItem("2speed").value;
amt = "";
if (1speed != "" && 2speed != "") {
var a = 1 * 1speed;
var b = 1 * 2speed;
if (a - b <= 9) {
alert(amt);
amt = doc.getDefault("general_spb_1_to_15");
} else if (a - b <= 15) {
amt = doc.getDefault("general_spb_16_to_25");
} else if (a - b <= 25) {
amt = doc.getDefault("general_spb_15_to_19");
} else if (a - b <= 29) {
amt = doc.getDefault("general_spb_26+");
}
doc.findItem("mcare_amount").value = amt;
alert(doc.findItem("mcare_amount").value = amt);
}
}
Default values are:
general_spb_1_to_15=30.00 || general_spb_16_to_25=40.00 || general_spb_26+=50.00
My problem is when amt is empty or 0 it is always going to general_spb_1_to_15=30.00. I am not sure how to fix this- can someone please help? The values that I am using are 1speed = 20 and 2speed = 25 which is negative or empty.
Assuming your browser engine is interpreting 1speed and 2speed as variables (some will, some won't -- variable names aren't supposed to start with numbers so it would probably be wise to replace these with speed1 and speed2)...
But assuming that, then the case that you describe is seeing a value of a - b = -5 when processing your if statements, which means that it is being caught by
if (a - b <= 9) {
alert(amt);
amt = doc.getDefault("general_spb_1_to_15");
}
To change the result you are getting, you should add another option to the if statement structure. Perhaps:
if (b > a)
{
//do something for this special case
} else if (a - b <= 9) {
alert(amt);
amt = doc.getDefault("general_spb_1_to_15");
} else if ...
You may also want to specifically handle the case where one or both of speed1/speed2 are empty as an else on the outer if block.

Error in JavaScript return code?

Here is the javascript code:
There is an error in code where nightSurcharges is added to total cost even if pickUptime is less than 20.
function TaxiFare() {
var baseFare = 2;
var costPerMile = 0.50;
var nightSurcharge = 0.50; // 8pm to 6am, every night //its flat 0.50 and not per mile
var milesTravelled = Number(document.getElementById("miles").value) || 0;
if ((milesTravelled < 1) || (milesTravelled > 200)) {
alert("You must enter 1 - 200 miles");
document.getElementById("miles").focus();
return false;
}
var pickupTime = Number(document.getElementById("putime").value) || 0;
if ((pickupTime == "") || (pickupTime < 0) || (pickupTime > 23)) {
alert("The time must be 0-23 hours");
document.getElementById("putime").focus();
return false;
}
var cost = baseFare + (costPerMile * milesTravelled);
// add the nightSurcharge to the cost if it is after
// 8pm or before 6am
if (pickupTime >= 20 || pickupTime < 6) {
cost += nightSurcharge;
}
alert("Your taxi fare is $" + cost.toFixed(2));
}
I want nightSurcharge to be added only when pickupTime is >=20, but that's not working right now.
Any help is appreciated. Thanks
This seems obvious to me.
if (pickupTime >= 20 || pickupTime < 6) {
cost += nightSurcharge;
}
This code right here adds nightSurcharge to the cost if pickupTime is greater than or equal to 20, OR less than 6. So of course it's added if it's less than 6.
if (pickupTime >= 20) {
cost += nightSurcharge;
}
Now it will only add to it if it's greater or equal to 20.
your code is:
if (pickupTime >= 20 || pickupTime < 6)
so if pickupTime is less then 6 it'll enter the if as well
http://jsfiddle.net/7rdzC/

Categories

Resources