JavaScript: Why is this causing an infinite loop? - javascript

I'm trying to find the largest number by finding the point at which the JavaScript number line wraps around. E.g., if it could only hold numbers 0, 1, 127 then I'd find 127 by using the fact that "127 + 1 = 0". So I made a function
function getLargestNumber ( )
{
var somethingBig = 12939123, last = (somethingBig - 1);
while ( ++somethingBig > ++last );
return last;
}
but that's causing an infinite loop (or crashing the browser for some other reason).
Is there anything wrong with the logic of my function?

JavaScript numbers are always stored as floating point numbers, not integers like in C. Floating point numbers don't "wrap around" the same way that a C integer will.
This might help you What is JavaScript's highest integer value that a Number can go to without losing precision?

It looks like the while loop will run forever because you are always incrementing both somethingBig and last, therefore somethingBig will always be larger:
while ( ++somethingBig > ++last );
I'm not sure exactly what you are trying to accomplish but this would be the cause of the infinite loop.
Hope this helps!

Related

Modulo - calculations error

Let me be brief. I'm trying to calculate
alert((Math.pow(7,35))%71)
but it gives me 61, when the result must be 70. What's wrong?
As others mentioned before with regards to using Math.pow(7,35), this resulting number is way too big for Javascript to handle.
To resolve your problem you need to use an external javascript library.
(Or write your own ;) )
Here are some examples of Javascript libraries that handle big numbers.
BigNum
Bignumber
I hope it helps.
The number you're using is too big for javascript. The max size of an int is 2^53 -- which is less than 7^35.
The only value which requires more precision is an intermediate result. So the problem can also be avoided without the need for higher precision variables when you have an algorithm that doesn't need the problematic intermediate result.
The following formula can be useful for that:
(a.b) % c = (a % c)(b % c) % c
This means Math.pow(7,35)%71 = ((Math.pow(7,17)%71) * (Math.pow(7,18)%71)) % 71.
Now the intermediate results are smaller, but might still be too big. So we need to split up further and to apply the modula operator on smaller intermediate results.
So you can do something like this:
Math.pow((Math.pow(7,7)%71),5)%71
But you probably need to do this for integer numbers wich are variable (otherwise, you could have avoided the problem by hardcoding the result).
So, you need to have an idea about the range of values you can expect and to define an algoritm that splits up the power calculation into pieces that will always have results that are small enough when the input is within the expected range.
And whatever you choose for a calculation like this, calculation with higher precision variables (using a specialized library) or a specilized algoritm, you should always assert the input to make sure your calculation returns a value only when you are sure it can deliver a correct value. Otherwise your implementation becomes unreliable for anyone who isn't aware of the range in which it is valid. Otherwise return an exception with a message that tells clearly which input or combination of inputs is the problem and why.

How to prevent a number from using number1"E"number2

I need help because if I try to write a number that has a whole bunch of zeroes, it will come out as num1Enum2.
ie: for a googol it would write "1E100".
I want it to actually write the number, rather than the shortened form. How would I do this?
Note: I want it to still be an integer rather than a string.
If you "write out" a number, you get a string. Period. "Writing out" means outputting a sequence of characters that represent the number. But that's what a string is: a sequence of characters.
A number like 1E100 is too big to represent as a normal-sized integer, even internally. To get a value that big as an integer, you'll have to use some sort of library to represent big integers. Search around for one. There are several, with names like "BigInt", "BigInteger", "BigNumber", "LongDecimal" and so on. They should all be able to store internally arbitrarily large integer values, and should all provide a way to turn that value into a string, which you can then write out. Pick one you like.
You could try a big number handling library, like big.js. Otherwise, your only solution will be to split your big numbers into arrays and write your own math functions to manipulate them -- something like this function to treat an array as an integer and increment it:
var longVal=[0];
// inherits global array longVal[]
// increments each element from right to left
function inc() {
for (var i=longVal.length - 1; i>=0; i--) {
if (++longVal[i] == 10) {
longVal[i] = 0;
if (!i) {
longVal.splice(0, 0, 0);
i++;
}
continue;
}
else break;
}
}
I think if you exceed the length limit of your array, you could probably change the if (++longVal[i] == 10) line to something like if (++longval[i] == 1000000000) for great justice, but you'd have to left pad each array element except the first with zeros to make it ten digits. I haven't tested that though. My answer is the concept, rather than the implementation.

Function returning NaN when I try to generate basic math operations

I am trying to generate randomly basic math operations(addition, subtractions, multiplication and division) and sometime my function returns NaN.
I used function parseInt(), but I still have the same problem. I will appreciate if anybody can help me with any suggestion.
Thank you in advance!
Here is my code:
function randNum(min,max)
{
var num = min+Math.floor((Math.random()*(max-min+1)));
return num;
}
var choose, operator, firstNum, secondNum,rightAnswer;
function getProb()
{
var chooseOp=randNum(1,4);
choose=parseInt(chooseOp);
if (choose==1)
{
oprator="+";
var choose1=randNum(0,10);
var choose2=randNum(0,10);
firstNum=parseInt(choose1);
secondNum=parseInt(choose2);
document.getElementById("mathProb").innerHTML=firstNum+operator+secondNum+"=";
rightAnswer=choose1 + choose2;
}
else if (choose==2)
{
operator="-";
var choose1=randNum(0,10);
var choose2=randNum(0,10);
firstNum=parseInt(choose1);
secondNum=parseInt(choose2);
document.getElementById("mathProb").innerHTML=firstNum+operator+secondNum+"=";
rightAnswer=firstNum - secondNum;
}
else if (choose==3)
{
operator="x";
var choose1=randNum(0,10);
var choose2=randNum(0,10);
firstNum=parseInt(choose1);
secondNum=parseInt(choose2);
document.getElementById("mathProb").innerHTML=firstNum+operator+secondNum+"=";
rightAnswer=choose1 * choose2;
}
else if (choose==4)
{
operator="/";
var choose1=randNum(0,10);
var choose2=randNum(0,10);
firstNum=parseInt(choose1);
secondNum=parseInt(choose2);
document.getElementById("mathProb").innerHTML=firstNum+operator+secondNum+"=";
rightAnswer=choose1/choose2;
}
}
When choose==1, operator is misspelled as oprator. If you correct it, problem is solved
http://jsfiddle.net/uERwd/2/
UPDATE:
Your code can be made shorter as: http://jsfiddle.net/uERwd/3/
Your division operation has the possibility of dividing by zero, which would return NaN.
Your "NaN" bug is here :
rightAnswer=choose1/choose2;
choose1 an choose2 are integer in [0, 1].
One time over 121, you're dividing 0 by 0, wich gives NaN.
And a little less than one time over 11, you're dividing a not null number by 0, wich gives Infinity.
You need to specify with a number that represent numeral system, tipically, base 10
http://www.w3schools.com/jsref/jsref_parseint.asp
Add the number 10 to the function call like this
firstNum = parseInt(choose1, 10);
When you randomly choose the division operator, it's possible to have zero come out for both choose1 and choose1, which means you attempt to evaluate rightAnswer = 0 / 0;. In Javascript, this equals NaN. Additionally, and this should happen more often, if you choose zero in the denominator any other number in the numerator the answer will come out as Infinity. Of course, zero over anything is zero.
It's a simple syntax error:
oprator="+"; // should be `operator`
That's why this statement...
firstNum+operator+secondNum+"=";
... will actually be evaluated as ...
firstNum+undefined+secondNum+"=";
The first pair will give you NaN, NaN + Number will be a NaN again, and NaN + String ("=") will result in NaN converted to string, then appended with '=' (hence resulting 'NaN=').
I'd strongly recommend placing "use strict"; line at the beginning of your scripts to catch such errors. With this, you'll get an error:
ReferenceError: assignment to undeclared variable oprator
... and won't need to make SO parse your script for errors instead. )
Sidenotes, I have plenty of them:
your randNum function will return you a Number, so no need to use parseInt (you may have to convert arguments of this function, but even that seems not to be necessary here) on its result;
if you divide by zero, you get Infinity; if you divide zero by zero, you get NaN as a result; be prepared or adjust the minimums. )
you violate DRY principle, repeating most of the statements outputting a result, why don't convert them into a function? Check this snippet (started by #sv_in, completed by me) for example how to do it.

Javascript: explain this one line of code to me please

I have this simple array:
var RedirUrl = new Array(4);
RedirUrl[0] = 'http://mafi.se/mf_redir/new_install_'+this_version+'.html';
RedirUrl[1] = 'http://ifurls.com/mf_redir/new_install_'+this_version+'.html';
RedirUrl[2] = 'http://ez.se/xml-update/mf_redir/new_install_'+this_version+'.html';
RedirUrl[3] = 'http://ilovre.net/mf_redir/new_install_'+this_version+'.html';
RedirUrl[4] = 'http://rihel.com/mf_redir/new_install_'+this_version+'.html';
and then
RedirUrl.sort(function() {return 0.5 - Math.random()})
The last bit is what is confusing me.
I understand the "sort" and I understand the Math.random but the return 0.5 confuses me... what exactly is that?
(Needless to say I downloaded it off the net as it does what i want it to do... but i just dont understand it.)
It's sorting the list of URLs with a sorting method that randomly returns values that are greater than or less than 0 in about half the cases each.
Math.random() returns a number betweeen 0 and 1. Therefore 0.5 - Math.random() is a randomly decided value between -0.5 and 0.5. About half of those values are greater than zero and half of those are less than zero.
So about half of the time the comparison function will say that the first object is greater than the second and half of the time it will say the opposite.
It's a simple way to randomly shuffle the array. As has been pointed out in the comments, it's not a good way to shuffle an array (because the distribution is not even).
This question has a working implementation of the known-good Fisher-Yates shuffle.
sort() takes a function for comparing values in an array as it's argument. Here the sort() method is told to give a random number between 0.0 and 1.0, and the 0.5 is there to make the random number go between -0.5 to 0.5, this randomly saying lesser or greater than.
A comparator function should return < 0 to indicate that the first value is smaller, > 0 to indicate that it's larger, and 0 to indicate equality. Math.random() returns a number between 0 and 1. So, by doing the subtraction, you get random ordering!
This would shuffle the array. If a function is used withing Array.sort() then it usually has two parameters which are compared Array.sort(function(a,b){}). A return value less than 0 indicates that a is before b, greater than 0 that a is after b and 0 that they have the same order. Using 0.5 - Math.random() means that you should get values greater or less than 0 at random.
Seems the script will randomly shuffle this array by having the compare function randomly returns a value between -0.5 and +0.5
Also it generates an array of length 4 but then fills it with 5 items
I suggest this format instead
var RedirUrl = [
'http://mafi.se/mf_redir/new_install_'+this_version+'.html',
'http://ifurls.com/mf_redir/new_install_'+this_version+'.html',
'http://ez.se/xml-update/mf_redir/new_install_'+this_version+'.html',
'http://ilovre.net/mf_redir/new_install_'+this_version+'.html',
'http://rihel.com/mf_redir/new_install_'+this_version+'.html'
]
Here sort will be performing a sort based on the comparison function that you pass to it.
In your case, it is:
function() {return 0.5 - Math.random()}
Assuming you are familiar with comparison based sorting, the function should return a negative value indicating that the left hand side value is less, zero if they are equal and positive if left hand side value is greater than the right hand side value, much like C function strcmp().
Looking into the function that you have, it will try to perform a random sort, that is try to shuffle the array.
On an additional note, this kind of shuffling algorithm is not an ideal one. It will be self contradictory. Since everything will occur at random, it may lead to situations where say, a.

What are the chances that JavaScript Math.Random() will create the same number twice in a row?

Is this correct? using - http://en.wikipedia.org/wiki/Binomial_probability
Looks like values are from .0000000000000000 to .9999999999999999
Probability of happening twice = p^2 = (1/9999999999999999)^2 = 1.0 e-32
I think I am missing something here?
Also, how does being a pseudo random number generator change this calculation?
Thank You.
In an ideal world Math.random() would be absolutely random, with one output being completely independent from another, which (assuming p=the probability of any given number being produced) results in a probably of p^2 for any value being repeated immediately after another (as others have already said).
In practice people want Math.random to be fast which means pseudo-random number generators are used by the engines. There are many different kinds of PRNG but the most basic is a linear congruential generator, which is basically a function along the lines of:
s(n + 1) = some_prime * s(n) + some_value mod some_other_prime
If such a generator is used then you won't see a value repeated until you've called random() some_other_prime times. You're guaranteed of that.
Relatively recently however it's become apparent that this kind of behaviour (coupled with seeding the PRNGs with the current time) could be used for some forms tracking have led to browsers doing a number of things that mean you can't assume anything about subsequent random() calls.
I think the probability of getting two numbers in a row is 1 divided by the range of the generator, assuming that it has a good distribution.
The reason for this is that the first number can be anything, and the second number needs to just be that number again, which means we don't care about the first number at all. The probability of getting the same number twice in a row is the same as the probability of getting any particular number once.
Getting some particular number twice in a row, e.g. two 0.5s in a row, would be p^2; however, if you just care about any number twice in a row, it's just p.
If the numbers were truly random, you'd expect them, indeed, to appear with probability 1/p, so twice that would be 1/p^2.
The value for p is not exactly the one you have though, because the numbers are being represented internally as binary. Figure out how many bits of mantissa the numbers have in javascript and use that for your combinatoric count.
The "pseudorandom" part is more interesting, because the properties of pseudorandom number generators vary. Knuth does some lovely work with that in Seminumerical Algorithms, but basically most usual PN generators have at least some spectral distributiuon. Cryptograp0hic PN generators are generally stronger.
Update: The amount of time shouldn't be significant. Whether it's a millisecond or a year, as long as you don't update the state The probabilities will stay the same.
The probability that you would get 2 given numbers is (1/p)^2, but the probability that you get 2 of same numbers (any) is 1/p. That is because the first number can be anything, and the second just needs to match that.
You can kind of find out, just let it run a few days :)
var last = 0.1;
var count = 0 | 0;
function rand(){
++count;
var num = Math.random();
if(num === last){
console.log('count: '+count+' num: '+num);
}
last = num;
}
while(true) rand();

Categories