Odd behavior with else if statement (javascript) - javascript

As far as I can tell the code works fine normally but when more information is added or edited then the if else statement starts behaving oddly. It's reading the percent value correctly but it's not returning the correct letter string.
var total = function (){
var earned = 0;
for(i = 0; i < Assignments.length; i++){
earned += parseInt(Assignments[i].earned);
}
var possible = 0;
for(i = 0; i < Assignments.length; i++){
possible += parseInt(Assignments[i].possible);
}
var percent = (Math.floor((earned/possible) * 100));
console.log(percent);
//grade letter
if (percent >= 90){
grade.innerHTML = '';
grade.innerHTML = 'A ' + percent + '%';
} else if (percent <= 89 && 80 >= percent){
grade.innerHTML = '';
grade.innerHTML = 'B ' + percent + '%';
} else if (percent <= 79 && 70 >= percent){
grade.innerHTML = '';
grade.innerHTML = 'C ' + percent + '%';
} else if (percent <= 69 && 60 >= percent){
grade.innerHTML = '';
grade.innerHTML = 'D ' + percent + '%';
} else if(percent <= 59 && 0 >= percent){
grade.innerHTML = '';
grade.innerHTML = 'F ' + percent + '%';
} else {grade.innerHTML = '';}
};
After a few inputs it will return something like this:
I think it might be the else if statements conflicting, but honestly I have no idea why this is behaving this way.

You have your comparisons backward in the else ifs, you're using 70 >= percent rather than percent >= 70 (and so on).
Separately, there's no reason to assign '' to innerHTML if you're about to assign something else to it, and there's no reason to reiterate the upper bound (percent <= 89 and such), because you're using else if, so the percent >= 90 branch will have already been followed. Reiterating them is also a maintenance problem (you'll change one but forget to change the other).
So:
if (percent >= 90) {
grade.innerHTML = 'A ' + percent + '%';
} else if (percent >= 80) {
grade.innerHTML = 'B ' + percent + '%';
} else if (percent >= 70) {
grade.innerHTML = 'C ' + percent + '%';
} else if (percent >= 60) {
grade.innerHTML = 'D ' + percent + '%';
} else if (percent >= 0) {
grade.innerHTML = 'F ' + percent + '%';
} else {
grade.innerHTML = '';
}
Or of course, you can use a map, since your grade boundaries are evenly divisible by 10:
// Somewhere central
var grades = {
6: 'D',
7: 'C',
8: 'B',
9: 'A',
10: 'A'
};
// ...then simply:
if (percent >= 0) {
grade.innerHTML = (grades[Math.floor(percent / 10)] || 'F') + ' ' + percent + '%';
} else {
grade.innerHTML = "Less than 0?!";
}
var grades = {
6: 'D',
7: 'C',
8: 'B',
9: 'A',
10: 'A'
};
function showGrade(percent) {
var grade;
if (percent >= 0) {
grade = (grades[Math.floor(percent / 10)] || 'F') + ' ' + percent + '%';
} else {
grade = "Less than 0?!";
}
snippet.log(grade);
}
var n;
for (n = 0; n <= 100; ++n) {
showGrade(n);
}
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

If-Else condition range looking wrong, try this code...
var total = function (){
var earned = 0, possible = 0;
for(i = 0; i < Assignments.length; i++){
possible += parseInt(Assignments[i].possible);
earned += parseInt(Assignments[i].earned);
}
var percent = (Math.floor((earned/possible) * 100));
console.log(percent);
//grade letter
if (percent >= 90){
grade.innerHTML = 'A ' + percent + '%';
} else if (percent >= 80 && percent <= 89){
grade.innerHTML = 'B ' + percent + '%';
} else if (percent >= 70 && percent <= 79){
grade.innerHTML = 'C ' + percent + '%';
} else if (percent >= 60 && percent <= 69){
grade.innerHTML = 'D ' + percent + '%';
} else if(percent >= 0 && percent <= 59){
grade.innerHTML = 'F ' + percent + '%';
} else {grade.innerHTML = '';}
};
Although i have optimized some code no need 2 loops there, you can sum earned, possible variable in single loop, and no need to .innerHTML = '' when you assigning value in element.

I found a nice post on efficiency using different methods of comparing things. I still suggest using a switch-block instead of if/else, but it's technically not better than your solution, but as I thinks it nicer to read. Here is a code snippet:
switch (true) {
case (0 <= val && val < 1000): /* do something */ break;
case (1000 <= val && val < 2000): /* do something */ break;
...
case (29000 <= val && val < 30000): /* do something */ break;
}
Taken from this post. There's also an interesting table (in the first answer)
Switch statement for greater-than/less-than
and different methods of making this work. I know this is actually not a solution for your answer, but it might come in handy if you need to add more if/else and are doing some huge lists with values.

Related

error shows on using && operator in chrome snippets

prompt("Enter your name");
var lifeExpectancy = Math.random() ;
lifeExpectancy = Math.floor(lifeExpectancy * 100) + 30;
// if (lifeExpectancy > 100){alert(lifeExpectancy + " Years, as old as Dinosaurs")}
if (lifeExpectancy <= 100 && > 75 ){
alert(lifeExpectancy + " Years , Many more birthdays to come !!!")
} else{
alert(lifeExpectancy + " Years.")
}
Shows error on using && and <= operators
You need to mention the name of variable again for the second comaprison
prompt("Enter your name");
var lifeExpectancy = Math.random() ;
lifeExpectancy = Math.floor(lifeExpectancy * 100) + 30;
if (lifeExpectancy <= 100 && lifeExpectancy > 75 ){
alert(lifeExpectancy + " Years , Many more birthdays to come !!!")
} else{
alert(lifeExpectancy + " Years.")
}

Simplified javascript some function with almost the same code

Hei, I'm working an app to simulate prices. I have a code like this.
function max110(x) {
if (x >= '1' && x <= '50') {
var sum = 120 * x;
hasil.value = 'Rp.' + parseFloat(sum * 1000);
} else if (x >= '51' && x <= '100') {
var sum = 115 * x;
hasil.value = 'Rp.' + parseFloat(sum * 1000);
} else if (x >= '101' && x <= '200') {
var sum = 110 * x;
hasil.value = 'Rp.' + parseFloat(sum * 1000);
} else {
hasil.value = 'error!';
}
}
function max115(x) {
if (x >= '1' && x <= '50') {
var sum = 125 * x;
hasil.value = 'Rp.' + parseFloat(sum * 1000);
} else if (x >= '51' && x <= '100') {
var sum = 120 * x;
hasil.value = 'Rp.' + parseFloat(sum * 1000);
} else if (x >= '101' && x <= '200') {
var sum = 115 * x;
hasil.value = 'Rp.' + parseFloat(sum * 1000);
} else {
hasil.value = 'error!';
}
}
And I still have some functions similar to that, it almost the same code I'm trying to make it simple, is it possible to make it in 1 function only?
Try:
function maxval(x,maxval) {
if(x >= '1' && x <= '50'){
var sum = (maxval+10)* x;
hasil.value = 'Rp.'+parseFloat(sum*1000);
}
else if (x >= '51' && x <= '100'){
var sum = (maxval+5)* x;
hasil.value = 'Rp.'+parseFloat(sum*1000);
}
else if(x >= '101' && x <= '200'){
var sum = (maxval)* x;
hasil.value = 'Rp.'+parseFloat(sum*1000);
}
else{
hasil.value = 'error!';
}
}
By the way i assumed that maxval increments by 5, Cant get you a better solution without getting more details about functionality.
This would be my implementation. I don't agree with how you're handling your integers, but it's your coding style. I pass in an object of choice that has all of the values that I want. You don't need the logic, just the values. I hope nobody gets mad that I monkeypatch String. I'm assuming that your variable x is a string.
String.prototype.isBetween = function(lower, upper){
int = parseInt(this)
return int >= parseInt(lower) && int <= parseInt(upper)
}
max110 = {0: 120, 1: 115, 2: 110}
max115 = {0: 125, 1: 120, 2: 115}
function max(x, values) {
let sum
hasil.value = ''
if (x.isBetween('1', '50')) {
sum = values['0'] * x
} else if (x.isBetween('51', '100')) {
sum = values['1'] * x
} else if (x.isBetween('101', '200')) {
sum = values['2'] * x
} else {
hasil.value = 'error'
}
hasil.value = hasil.value ? 'error' : 'Rp.'+parseFloat(sum*1000);
}
function max(x, extra) {
var sum_number = extra;
if(x >= '1' && x <= '50'){
sum_number += 120;
}
else if (x >= '51' && x <= '100'){
sum_number += 115;
}
else if(x >= '101' && x <= '200'){
sum_number += 110;
}
if(x < 1 && x > 200){
hasil.value = 'error!';
} else {
hasil.value = 'Rp.'+parseFloat((sum_number) * x *1000);
}
}
parameter extra can be 0 or 5 for function max110 or max115
Basically, you have two function which works the same way and returns the same with different values.
The different values yould be stored in an array and you could use a single function for getting the index and then take the needed value out of the array with that index.
So you need a better organisation of types of the variables, which if uses as number, it should be number and also for comparison, then it should be a number on both sides of the condition.
Use a pure function, which does not alter a state of something, which is not given into the function.
Use a check in the function for unwanted values and exit early with a first check at the lower border, in your case, it is zero and below, return -1, because that is not an index of an array (and it is usually used to denote, that no index is found, like with Array#indexOf).
Then take the upper border for a check end exit early with a index value, no need for continuing else if structures.
At the end return as well -1 for not found index.
Together:
function getValue(x, maxArray) {
var index = getIndex(x);
if (index in maxArray) {
return 'Rp.' + maxArray[index] * x * 1000;
}
return 'error!';
}
function getIndex(x) {
if (!x || x < 0) {
return -1;
}
if (x <= 50) {
return 0;
}
if (x <= 100) {
return 1;
}
if (x <= 200) {
return 2;
}
return -1;
}
var max110 = [120, 115, 110],
max115 = [125, 120, 115];
console.log(getValue(-1, max110));
console.log(getValue(10, max110));
console.log(getValue(10, max115));

Run multiple else if statements

When I run this code, only the INVALID (over 100) and High Distinction works. Any number below 80 also shows High Distinction. What have I done wrong?
function calculateGrade() {
var fvalue = Number(prompt('Please enter final score for unit. Enter a whole number only'));
document.write('The final score entered is ' + fvalue + '<br />');
if (fvalue > 100) {
document.write('INVALID');
} else if (80 <= fvalue <= 100) {
document.write('High Distinction');
} else if (70 <= fvalue <= 79) {
document.write('Distinction');
} else if (60 <= fvalue <= 69) {
document.write('Credit');
} else if (50 <= fvalue <= 59) {
document.write('Pass');
} else if (0 <= fvalue <= 49) {
document.write('Fail');
} else if (fvalue < 0) {
document.write('INVALID');
}
}
calculateGrade()
Your comparison syntax is invalid. You need to check one boundary at a time:
if (80 <= fvalue && fvalue <= 100) {
Same for the others.
To take it a step further, you only need to check one boundary, because the higher end is excluded by the else:
if (fvalue > 100) {
document.write('INVALID');
} else if (80 <= fvalue) {
document.write('High Distinction');
} else if (70 <= fvalue) {
// ...
This isn't java.
But you can surely try this.
else if ( (fvalue >= 80) && (fvalue<= 100)) {
document.write('High Distinction');

How do you return a value if it exceeds a certain number?

I am making a app for a board game for school, the game is based on Game of the Goose. In this game once you are on a certain spot and you exceed the highest number it sets you back the value that is left. For example, if you are at 64 and you roll 4 you return to spot 66 because 67 is the highest number. I'm using a math.random and a math.floor to add a number to the player from 1 to 6.
*edit:
Here is the code i am writing, it's a bit sloppy though, sorry for that.
var players = [
{
name: "Speler 1",
positie: 0
},
{
name: "Speler 2",
positie: 0
},
{
name: "Speler 3",
positie: 0
},
{
name: "Speler 4",
positie: 0
}
];
var position = 0;
var currentPlayer = players[position];
function rolClick(){
if (position >= players.length){
position = 0;
};
currentPlayer = players[position++];
var rollen = Math.floor(Math.random() * 6) + 1;
if (rollen === 1){
currentPlayer.positie += 1;
}else if(rollen === 2){
currentPlayer.positie += 2;
}else if(rollen === 3){
currentPlayer.positie += 3;
}else if(rollen === 4){
currentPlayer.positie += 4;
}else if(rollen === 5){
currentPlayer.positie += 5;
}else if(rollen === 6){
currentPlayer.positie += 6;
}};
Suppose the variable that you are increasing is called current.
function getRandomBetween(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
var highest = 67;
current += getRandomBetween(1, 6);
if(current > highest) return highest-1;
Something like this..
function onRoll(this) {
currentVal=this.value;
x=Math.random();//Ensure you have your limitations of random number in place;
newVal=currentVal+x;
if(newVal>66)//whatever your limit
return 66;
else
return newVal;
}
This script do what you want (I think):
maxValue = 67
dice = Math.floor((Math.random() * 10) + 1)
oldValue = 64
if(oldValue + dice > maxValue){
alert("You reached the maximum. Your Value is set to " + (maxValue-1))
newValue = maxValue-1
}else{
newValue = oldValue+dice
}
You should read the if Statements...
here you can read and learn it:
http://www.w3schools.com/js/js_if_else.asp

Converting big numbers to bigger factors in JavaScript

I have counter and sometimes it can get very big number, so I need to convert numbers like:
1300 => 1.3K
1000000 => 1M
And so on. How is this possible in JavaScript?
// Truncate a number to ind decimal places
function truncNb(Nb, ind) {
var _nb = Nb * (Math.pow(10,ind));
_nb = Math.floor(_nb);
_nb = _nb / (Math.pow(10,ind));
return _nb;
}
// convert a big number to k,M,G
function int2roundKMG(val) {
var _str = "";
if (val >= 1e9) { _str = truncNb((val/1e9), 1) + ' G';
} else if (val >= 1e6) { _str = truncNb((val/1e6), 1) + ' M';
} else if (val >= 1e3) { _str = truncNb((val/1e3), 1) + ' k';
} else { _str = parseInt(val);
}
return _str;
}
I picked up a nifty bit of code when looking for something to abbreviate and label byte sizes (e.g. 1024 bytes -> "1 KB") and changed it just a bit to suit your needs (1000 -> "1 K").
function abbreviate_number(num) {
var sizes = ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'];
if (num < 1000) return num;
var i = parseInt(Math.floor(Math.log(num) / Math.log(1000)));
return ((i == 0) ? (num / Math.pow(1000, i)) : (num / Math.pow(1000, i)).toFixed(1)) + ' ' + sizes[i]; // use .round() in place of .toFixed if you don't want the decimal
};
Just for reference, here's what I needed.
function format_bytes(bytes) {
var sizes = ['Bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
if (bytes == 0) return '';
if (bytes == 1) return '1 Byte';
var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
return ((i == 0)? (bytes / Math.pow(1024, i)) : (bytes / Math.pow(1024, i)).toFixed(1)) + ' ' + sizes[i];
};
Pseudocode:
factor = 0;
while (value > 1000) {
value = value/1000;
factor++;
}
output value (you might perhaps limit output to 3 decimal places)
convert factor to unit and output (0 = none, 1 = K, 2 = M, 3 = G...)
You could just use a classic cascading number formatter of sorts
function format_num(num) {
if( num < 1000 )
return num;
else if( num < 1000000 )
return parseInt(num / 1000) + "K";
else if( num < 1000000000 )
return parseInt(num / 1000000) + "M";
//....
}
You just have to take care of rounding appropriately.
I came up to these answers late when I was looking for a clean way to do it but just in case if anyone was looking for copy pasting an angular filter doing that here is mine. same logic as above responses:)
just to make you sure for 001234 it returns 1k
html:
<div ng-repeat="d in data>
<div class="numbers">{{d | KGMPformat}}</div>
</div>
js:
// controller:
$scope.data = [123,12345,1234567,12345678,12345678901]
// filter:
(function(app) {
app.filter('KGMPformat', function() {
return function(value) {
if (value<1e3) return value;
if (value<1e6) return (value - value%1e3)/1e3 + "K";
if (value<1e9) return (value - value%1e6)/1e6 + "G";
if (value<1e12) return (value - value%1e9)/1e9 + "M";
if (value<1e15) return (value - value%1e12)/1e12 + "P";
return value;
};
});
})(myApp);

Categories

Resources