returning NaN and Undefined in JavaScript - javascript

var currDice, totDice, dice, complete;
function moveIt(){
dice = Math.floor(Math.random()*6) + 1,
currDice = 40,
totDice = totDice+complete,
complete = dice * currDice
return totDice;
};
The function moveIt returns NaN.
It should return multiple of 40 till six randomly and keep the previous value.
If I remove it returns Undefined.
I know it is a scope problem. Please help.

You are using complete before initialising it! you habe to swap your lines of code:
function moveIt(beforeTotal) {
var dice = Math.floor(Math.random()*6) + 1;
var currDice = 40;
var complete = dice * currDice;
var totDice = (beforeTotal || 0)+complete;
return totDice;
};
var total = moveIt();
console.log(total);
total = moveIt(total);
console.log(total);
I try to point out how this method work.
You can call this function without an inital value. Then (beforeTotal || 0) is (undefined || 0) and will evaluate to 0, that's JS logic, and you get the result for one dice.
If you pass a value to this function it will be used to add complete to it. By passing 1000 and complete gets 120, you get 1120 out of it.
All other variables are only available in this function.

Initialy totDIce is undefined and when you add undefined to something, you get the value casted to NaN
function moveIt(){
//memoizing the mutable value as key of the function itself
moveIt.totDice = moveIt.totDice || 0;
// you might wanna wrap it with parseInt()/Math.floor()/Math.ceil()
var dice = Math.floor(Math.random()*6) + 1;
var currDice = 40;
var complete = dice * currDice;
var totDice = totDice+complete;
return moveIt.totDice ;
};

var totDice; will have undefined and that's why you get NaN
Assign totDice = 0 on the first line...
Also move complete = dice * currDice line above because complete has no value yet
var currDice, totDice = 0, dice, complete;
function moveIt(){
dice = Math.floor(Math.random()*6) + 1,
currDice = 40,
complete = dice * currDice,
totDice = totDice+complete
return totDice;
};

you can use the browser's integrated console.
In Chrome: Tools > Javascript Console. Or CTRL + SHIFT + J. There you can console.log from your code and watch it there, or you can use the Sources tab (at the top of the panel). Navigate to the file, click on it and you can put a breakpoint in the line you want by ckicking the line number.
In Firefox: Tools > development > Web console. Or CTRL + SHIFT + K. Yu can debug in a similar fashion like the aforementioned.
You can also use tools like Firebug. See https://getfirebug.com/wiki/index.php/Script_Debugging

Related

JavaScript equation returning stinky NaN value

var shaftDepth = 1;
var nextShaftDepth = ((maxThreshold - shaftDepth) / 20) + shaftDepth;
var maxThreshold = 10;
The equation for nextShaftDepth spits out an NaN value.
For context, I'm planning to have an "upgrade" in my game which decreases the distance of "shaftDepth" to "maxThreshold" by 5%. To do this, shaftDepth = nextShaftDepth after the formula is done.
"nextShaftDepth" is expected to be equal to 1.45, but instead it just returns an NaN value. Am I doing approaching this wrong or is my syntax incorrect? Thanks.
var is hoisted, it will be undefined as you're trying to access it before the declaration , change your code to
var shaftDepth = 1;
var maxThreshold = 10;
var nextShaftDepth = ((maxThreshold - shaftDepth) / 20) + shaftDepth;

Finding the greatest prime factor of an integer in Javascript

I am trying to write a simple program to find the greatest prime factor of an integer in JavaScript. The code I have written to do this follows:
let ans;
function factor(target, half) {
for (let i = 2; i < half; i++) {
if (target % i == 0) {
ans = target / i;
factor(ans, ans / 2);
}
}
}
factor(30, 15);
console.log(ans);
Now whether or not this code is an efficient solution to the problem or if it even works at all is beyond my issue with it: When I follow breakpoints set at each line of the factor function, I see that right after i = 2, target = 5, half = 2.5, and ans = 5, the value of target and half jump back up to 15 and 7.5 respectively. However, I do not see where in my code the values are told to change.
You're calling the function recursively, and each call to the function gets its own target, half, and i variables. In the first call to factor, target is 30 and half is 15. Then you call it again with the arguments 15 and 7.5; that inner call to factor gets its own target (15) and half (7.5), but the outer call still has its copies (30) and (15). This continues when you call factor again recursively, creating a third set, etc. When you step out of the innermost call, its variables disappear and you see the ones that are for the call that called it.
It may be clearer with a simpler example:
function countdown(value, indent) {
var twice = value * 2;
console.log(indent + "[before] value = " + value + ", twice = " + twice);
if (value > 0) {
countdown(value - 1, indent + " ");
}
console.log(indent + "[after] value = " + value + ", twice = " + twice);
}
countdown(3, "");
.as-console-wrapper {
max-height: 100% !important;
}
The output of that is:
[before] value = 3, twice = 6
[before] value = 2, twice = 4
[before] value = 1, twice = 2
[before] value = 0, twice = 0
[after] value = 0, twice = 0
[after] value = 1, twice = 2
[after] value = 2, twice = 4
[after] value = 3, twice = 6
As you can see, the values for value and twice in the outer call aren't changed by making the inner call. Each call gets its own set of variables.

Easy- Function arguments

I'm currently struggling with getting the below calcRatio function calculate properly. This is probably basic maths!
The below function works as expected:
function calcRatio(){
var r = frontRing.value/backCog.value;
return r;
}
e.g. frontRing = 52, backCog = 11 r=4.7272....
The below gives me the wrong result:
function calcRatio(){
var r = frontRing.value/(backCog.value + 5);
return r;
}
e.g. frontRing = 52, backCog = 11 r=0.4521.
I ultimately want the 5 to be swapped with an argument.
I am also unable to set the frontRing and backCog variable as .value's without doing it within the function. Could this be causing the issue?
Codepen link
When you expect the extracted value to be a string and have additional computations, it is preferred you use either
parseInt( value , 10) - for integers
parseFloat( value ) - for decimals
In the use case var r = frontRing.value/(backCog.value + 5);
backCog.value is a string since it it a value of input element. When you use + to add a number, it performs a concatenation instead of addition.
var backCogValue = backCog.value; // "11";
"11" + 5 --> 115 and not 16 as you expected.
So the right way to write this piece of code is to use either of the above methods before you want to add a number.
var frontRingValue = parseFloat(frontRing.value);
var backCogValue = parseFloat(backCog.value);
var r = (frontRingValue/ (backCogValue + 5)).toFixed(4);
toFixed is use to format into the number of decimal points that you are expecting.
If 5 is the argument that is passed to the function, then your code will look like
function calcRatio(param) {
var frontRingValue = parseFloat(frontRing.value);
var backCogValue = parseFloat(backCog.value);
var paramValue = parseFloat(paramValue);
var r = (frontRingValue/ (backCogValue + paramValue)).toFixed(4);
}

How to detect change of variable with formula

I have this variable (levelFormula) that contains a formula and then is updated via the output of another variable
var points = 100,
levelFormula = (Math.sqrt(2 * points + 255) - 5) / 10;
In other words, if points gets updated then so does levelFormula. The question is, how do I detect when the value of levelFormula gets changed?
As mentioned in the comments,
var previousLevelFormula; // should be separated with below scope
...
var points = 100; // I guess it's from function parameter, because it will be changed so you need detection changes of levelFormula
var levelFormula = (Math.sqrt(2 * points + 255) - 5) / 10;
if (previousLevelFormula && previousLevelFormula != levelFormula) {
// it's changed
}
previousLevelFormula = levelFormula; // update previous value

Javascript: generate random numbers in range, avoiding previous two

I'm creating a slider with 6 slides, and I want to randomly move between them, making sure that neither of the previous two slides are shown as the next slide. The functionality doesn't really matter, since what I'm really doing is generating random numbers and keeping track of the previous two. The first slide is always numbered 1, so for the first two iterations that'll be one of the previous numbers that can't be used.
Here's what I have so far, and it works fine for generating the random numbers in the range, but 'caching' the last two values doesn't work reliably:
var rand = Math.floor(Math.random() * 6) + 1;
var prev1 = 1;
var prev2;
function randomSlide() {
// 5 second interval between slides
// Don't show either of previous two slides next
random = setInterval(function() {
prev2 = prev1;
prev1 = rand;
do {
rand = Math.floor(Math.random() * 6) + 1;
} while (rand == prev1 || rand == prev2);
prev1 = rand;
$('#slider').anythingSlider(rand);
//console.log(prev1,prev2);
}, 5000);
}
function firstSlide() {
firstTime = setTimeout(function() {
randomSlide();
}, 5000);
}
firstSlide();
randomSlide();
It's quite simple I think but my brain's getting frazzled trying to parse the values of the two 'cache' variables at the first, and then each subsequent, iteration.
I'm executing a single iteration at the beginning because if randomSlide() executes on load then the first (welcome) slide doesn't get a chance to display.
When you do the prev1 = rand the second time after you've changed the value of rand, you're assigning the new slide's number to it. The next time you enter the loop you do prev2 = prev1, and since prev1 == rand it means that now all three variables prev1, prev2 and rand are the same. Just remove the second prev1 = rand.
Another issue is that you set the interval twice: first you call firstSlide() which executes randomSlide() after a 5 second delay (which sets one interval), then right after you call randomSlide() again which sets another interval.
Here's another (simpler?) approach to getting the result:
<script>
// Return a random number from 1 to 6, exclude
// the last two numbers.
var getRandom = (function() {
var a = [1,2,3,4,5,6];
return function() {
var i = (Math.random() * 4 ) | 0;
a[5] = a.splice(i,1);
return a[5];
}
}());
function writeRandom() {
document.getElementById('d0').innerHTML += getRandom() + '<br>';
}
setInterval(writeRandom, 100)
</script>
<div id="d0"></div>
Not exactly random for the first 2 iterations, but you can fix that by randomising the array when it's initialised. But likely it doesn't matter for a slide show.
It's less code, but the splice part makes it slower in the browsers I tested. My version of the OP is:
var getRandom2 = (function() {
var r0 = r1 = r2 = 1;
return function() {
r0 = r1;
r1 = r2;
do {
r2 = Math.floor(Math.random() * 6) + 1;
} while (r2 == r0 || r2 == r1);
return r1;
}
}());

Categories