Simple programming math - javascript

I'm trying to randomize objects in an object.
do{
e = enemyList[Math.floor(enemyList.length * Math.random())];
} while (e.level > (player.level + 5) && e.level < (player.level - 5));
return e;
How would I make it so "e" has to be between 5 levels above and 5 levels below in order for the loop to stop?
Yeah this is really easy, but my head hurts for some reason :p

I believe you should be using an or not an and. If it is 5 below OR if it is 5 above. Otherwise the condition will never be met.

You have the comparisons the wrong way round (+ should be - and vice versa):
} while (e.level > (player.level - 5) && e.level < (player.level + 5));
(The wording of your question is somewhat ambiguous; it could be that you should be using >= and <= instead of > and <.)

Related

Javascript: How to recursively return a counter?

In the example below, I don't want to make a counter as a param. Rather, I just want to return '+ 1' each time so that what gets returned is the number of steps it takes. My issue lies with the base case. If I do return + 1, I get the correct number of steps plus one additional step so I tried just return but that delivers NaN. Is it even possible?
var numberOfSteps = function(num) {
if (num == 0) {
return;
} else {
if (num % 2 == 0) {
return 1 + numberOfSteps(num/2);
} else {
return 1 + numberOfSteps(num - 1);
}
}
};
edit : The goal is to track how many steps it takes to reduce a number to 0. If it's even, divide by 2 or else subtract by 1. Ultimately, I want to return the number of steps it takes for any given number to get reduced to 0 following those rules
I hope the point has gotten through in the long comment thread and other answers that return + 1 is equivalent to return (+1), that is, return the integer positive one. And since there are no steps to take once you've reached zero, +1 is the wrong answer. Similarly, a plain return is functionally equivalent to return undefined. But undefined is not a number, and you're going to run into problems if you later try to add 1 to it. So the solution from the comments or other answers to return the correct number of steps, which in this case 0, will fix your code.
I would like to point out another way to solve this, though:
const numberOfSteps = (n) =>
n <= 0
? 0
: 1 + numberOfSteps (n % 2 == 0 ? n / 2 : n - 1)
console .log (numberOfSteps (12))
There are superficial differences here from the other solutions, such as using an arrow function, using a conditional statement (ternary) rather than if-statements, and using <= 0 instead of < 0 to avoid possible infinite loops on negative numbers.
But the fundamental difference is that this code only has one recursive branch. I think this is a better match to the problem.
We can think of this as a function which answers "How many steps does it take to reach 0 from our input number if each step cuts even numbers in half and subtracts one from odd ones?" Well that logically leads to a base case (we're already at 0) so have to return 0, and a recursive one (we're at some positive integer) so have to add 1 to the total steps required from our next entry.
By doing this single recursive call and adding one to the result, we make it clearer what the recursion is doing.
If this is unclear, then this alternative might show what I mean:
const takeStep = (n) =>
n % 2 == 0 ? n / 2 : n - 1
const numberOfSteps = (n) =>
n <= 0
? 0
: 1 + numberOfSteps (takeStep (n))
Think you just need to return 0 when it's...zero.
var numberOfSteps = function(num) {
if (num == 0) {
return 0;
} else {
if (num % 2 == 0) {
return 1 + numberOfSteps(num/2);
} else {
return 1 + numberOfSteps(num - 1);
}
}
}
return + 1 maybe doesn't do what you think it does: it returns the number 1. + here means positive not negative, there is no addition or subtraction going on. It will also give you one too many steps.
return; by itself returns undefined, which when converted to a Number, translates to NaN, because, well, it's not a number.

Round bracket in logical operator in jsFiddle

Not sure this problem is because of a bug in jsFiddle or my misunderstanding of the round bracket of javascript. I have this code:
let x = 5
(x > 0) && console.log('hello')
This doesn't work. However, the following without bracket works.
x > 0 && console.log('hello')
My impression is that i can use the round brackets in condition to group things together. I have no idea why my first line of code does not work. Is it my misunderstanding of round bracket?
I am actually trying to teach someone a more advance example in this jsFiddle code. https://jsfiddle.net/x616atk0/
It does not work, because you're missing a semicolon after let x = 5
The code should be:
let x = 5;
(x > 0) && console.log('hello');
Otherwise, your code can be translated to this:
let x = 5(x > 0) && console.log('hello');
And of course 5 isn't a function, and x (which you're using in the expression which evaluated value will be passed as argument) isn't defined yet.
The error is misleading because you're using the same variable that you're defining as argument. If you had
let x = 5
(5 > 0) && console.log('hello');
You would get: TypeError: 5 is not a function which is exactly the problem.
This is why semicolons are important!
Do you recommend using semicolons after every statement in JavaScript?
yes, I absolutely do
You forgot to put semicolons at the end of your lines, which is resulting in the error. When you do this:
let x = 5
let y = 4
x > 0 && console.log('code 4')
(x > 0) && (y > 0) && console.log('code 5');
because the third line ends in a ), the interpreter thinks you're calling the result of console.log with the (x > 0) argument:
let x = 5
let y = 4
x > 0 && console.log('code 4')(x > 0) && (y > 0) && console.log('code 5');
But console.log returns undefined: it doesn't return a function, so of course you can't call it as a function.
Always use semicolons if you're just still learning the language, or you can easily trip yourself up.
Also, what you're doing is not a good way of doing things; while it's an interesting language quirk, it's better to test for conditions explicitly using if or the ternary operator than to use && for that.

Building Javascript Calculator

I am trying to build a calculator in javascript but I am stuck and don't know how to proceed. every time someone click on 1 + 1 / 2, for exemple I am creating an array that pushes everything that was typed so in the case above the array would be
[1, "+", 1, "/", 2];
However, I can't figure it out how to transform this array into an actual mathematical value.
I had an idea of looping through all elements
like this:
for(var i=0; i<arrayCharacters.length ;i++){
if(arrayCharacters[i] != "*" || arrayCharacters[i] != "/" || arrayCharacters[i] != "+" || arrayCharacters[i] != "*"){
arrayNumbers.push(arrayCharacters.slice(0, i));
console.log(arrayNumbers);
}
}
It's very incomplete because I got stuck. Can anyone help me?
var result=eval(arrayCharacters.join(""));
You could also parse the expression manually, however this requires building up a tree, as math isnt evaluated left to right.
If you really want to parse it on your own (which is far better then eval), you could use a math notation that really goes from left to right , so its much easier to parse ( As #Scott suggested). An implementation:
var stack=[];
var arrayCharacters=[1,2,"/",1,"+"];
for(var i=0;i<arrayCharacters.length;i++){
var char=arrayCharacters[i];
if(typeof char==="number"){
stack.push(char);
continue;
}
var op2=stack.pop()||0;
var op1=stack.pop()||0;
var res;
if(char=="+"){
res=op1+op2;
}
if(char=="-"){
res=op1-op2;
}
if(char=="*"){
res=op1*op2;
}
if(char=="/"){
res=op1/op2;
}
stack.push(res);
}
var result=stack.pop();
Math Syntax (RPN (1)):
1+2 => 1 2 +
1/2+3 => 1 2 / 3 +
1+2/3 => 1 2 3 / +
(1+2)/3 => 1 2 + 3 /
1/2/3+4/5/6 => 1 2 / 3 / 4 5 / 6 / +
http://jsbin.com/zofeqitiba/edit?console
"eval" function is a very good choice in your case. Also you can use the math.js library, which comes with a powerful expression parser.
http://mathjs.org

check whether the number is nearly equal javascript

I want to know whether it is possible?
Let Suppose:
var a = 2592;
var b = 2584;
if(a nearly equal to b) {
// do something
}
Like so.
var diff = Math.abs( a - b );
if( diff > 50 ) {
console.log('diff greater than 50');
}
That would compare if the absolute difference is greater than 50 using Math.abs and simple comparison.
Here's the old school way to do it...
approxeq = function(v1, v2, epsilon) {
if (epsilon == null) {
epsilon = 0.001;
}
return Math.abs(v1 - v2) < epsilon;
};
so,
approxeq(5,5.000001)
is true, while
approxeq(5,5.1)
is false.
You can adjust pass in epsilons explicitly to suit your needs. One part in a thousand usually covers my javascript roundoff issues.
var ratio = 0;
if ( a > b) {
ratio = b / a;
}
else {
ratio = a / b;
}
if (ratio > 0.90) {
//do something
}
One line Es6 way version of The Software Barbarian:
const approxeq = (v1, v2, epsilon = 0.001) => Math.abs(v1 - v2) <= epsilon;
console.log(approxeq(3.33333, 3.33322)); // true
console.log(approxeq(2.3, 2.33322)); // false
console.log(approxeq(3, 4, 1)); // true
I changed it to include the number in the margin. So with an epsilon margin of 1 approxeq between 1 and 2 is true
Floating point comparison gets complicated in a hurry. It's not as simple as diff less than epsilon in a lot of cases.
Here's an article about the subject, though not javascript specific.
https://floating-point-gui.de/errors/comparison/
TLDR:
When one of the numbers being compared is very close to zero, subtracting the smaller from the larger can lose digits of precision, making the diff appear smaller than it is (or zero).
Very small numbers with different signs work in a weird way.
Dividing by zero will cause problems.
In the article is a function (java) which solves better for these cases:
public static boolean nearlyEqual(float a, float b, float epsilon) {
final float absA = Math.abs(a);
final float absB = Math.abs(b);
final float diff = Math.abs(a - b);
if (a == b) { // shortcut, handles infinities
return true;
} else if (a == 0 || b == 0 || (absA + absB < Float.MIN_NORMAL)) {
// a or b is zero or both are extremely close to it
// relative error is less meaningful here
return diff < (epsilon * Float.MIN_NORMAL);
} else { // use relative error
return diff / Math.min((absA + absB), Float.MAX_VALUE) < epsilon;
}
}
Before you complain: Yes, that's Java, so you'd have to rewrite it in Javascript. It's just to illustrate the algorithm and it's just copied from the article.
I'm still looking for a thorough solution to this problem, ideally with an NPM package so I don't have to figure this out again every time I need it.
Edit: I've found a package which implements the solution from the article linked above (which has the same link in their readme).
https://www.npmjs.com/package/#intocode-io/nearly-equal
This will be a less error-prone solution than others shown in other answers. There are several npm packages which implement the naive solutions which have error cases near zero as described above. Make sure you look at the source before you use them.

if number is between two numbers by plus/minus 10 addclass

http://jsfiddle.net/kM8xE/2/
If I have the divs
​
<div class="value">15</div>
<div class="value2">20</div>​
and jQuery
var actual = $(".value").html();
var comparison = $(".value2").html();
how can i add class .isbetween to .value2 if it's html value is between +/-10 of the html for .value ie. for this eg. a value between 5 and 25.
I am not too good but i have tried and it doesn't work.
if(parseInt(actual)-10 <= parseInt(comparison) <= parseInt(actual)+10){
$(".value2").addClass("isbetween");
}
if (Math.abs(actual - comparison) <= 10) {
//they're within 10
}
The reason this doesn't work is that you can't chain comparisons like this:
5 < x < 10
In Javascript (and other languages with c-like syntax), you have to make two separate comparisons, and use the boolean and operator (&&) to chain the comparisons together:
var actualValue = parseInt(actual);
var comparisonValue = parseInt(comparison);
if(actualValue - 10 <= comparisonValue && comparisonValue <= actualValue + 10) {
$(".value2").addClass("isbetween");
}
Also, don't repeat yourself. Do the conversion once, and store it in a local variable. This makes the code much more readable.
This can be made even more simple by using a concept called absolute value. Then you can just do your difference, and see if its absolute value is less than or equal to ten.
var delta = Math.abs(parseInt(actual) - parseInt(comparison));
if(delta <= 10) {
$(".value2").addClass("isbetween");
}
You have to get the two values, convert them to numbers, compare the absolute value of their difference and then add the class if it meets your condition:
var v1 = +$(".value").text();
var v2 = +$(".value2").text();
if (Math.abs(v1 - v2) <= 10) {
$(".value2").addClass("isbetween");
}

Categories