Random number extractor getting weird values - javascript

I'm trying to get a random integer which is between two given values and has not been extracted yet with javascript.
To do that, I'm using the following code:
var extracted = [];
function rand(){
var from = document.getElementById('from').value;
var to = document.getElementById('to').value;
var number = Math.floor(from) + Math.floor(Math.random() * to);
var alreadyextracted = (extracted.indexOf(number) > -1);
if(alreadyextracted){
var maximum = Math.floor(to) - Math.floor(from);
var count = extracted.length;
if(count > maximum){document.getElementById('result').innerHTML='All numbers have been extracted.';}
else{rand();}
}
else{document.getElementById('result').innerHTML=number;
extracted.push(number);
if(extracted[0] == number){var content = number;}
else{var before = document.getElementById('got').innerHTML;
var content = number + ', ' + before;}
document.getElementById('got').innerHTML= content;
}
}
From: <input id="from" value="1">
To: <input id="to" value="10">
<input type="button" value="Extract" onclick="rand()">
<div id="result"></div>
<div id="desc">Already extracted numbers:</div>
<div id="got"></div>
It works fine if i put a "from" value which is lower than 10, but, if it is greater, it gets a completely random integer and randomly says that all numbers have been extracted even if it's not true.
I don't see anything in the firefox console.
What could be the problem?

You're doing it all wrong.
Fill an array with all of your range of numbers from smallest to largest.
Use a Fisher/Yates/Knuth shuffle to mix the array.
Draw out as many numbers as you need.
(No code included on purpose because I didn't fix your problem)

Spender is not wrong but the problem lies in the way you generate you random numbers:
var number = Math.floor(from) + Math.floor(Math.random() * to);
That's not the proper way to generate a number between min and max. This should be:
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
Use the method proposed by spender and then pick an element in the remaining set using this function (In this case min will be 0 and max the number of remaining elements-1)

Related

Pick random combination from 194481 possibilities

I have a file of 194481 permutations for
0,1,2,3,4,5,6,...,21
which looks like this;
[0,0,0,0],[0,0,0,1],[0,0,0,2],[0,0,0,3],[0,0,0,4],[0,0,0,5],[0,0,0,6],[0,0,0,7],[0,0,0,8],[0,0,0,9],[0,0,0,10],[0,0,0,11],[0,0,0,12],[0,0,0,13],[0,0,0,14],[0,0,0,15],[0,0,0,16],[0,0,0,17],[0,0,0,18],[0,0,0,19],[0,0,0,20],[0,0,1,0],[0,0,1,1],[0,0,1,2],[0,0,1,3],[0,0,1,4],[0,0,1,5],[0,0,1,6],[0,0,1,7],[0,0,1,8],[0,0,1,9],[0,0,1,10],[0,0,1,11],[0,0,1,12],[0,0,1,13],[0,0,1,14],[0,0,1,15],[0,0,1,16],[0,0,1,17],[0,0,1,18],[0,0,1,19],[0,0,1,20],[0,0,2,0],[0,0,2,1],[0,0,2,2],[0,0,2,3],[0,0,2,4],[0,0,2,5],[0,0,2,6],[0,0,2,7],[0,0,2,8],[0,0,2,9],[0,0,2,10],[0,0,2,11],[0,0,2,12],[0,0,2,13],[0,0,2,14],[0,0,2,15],[0,0,2,16],[0,0,2,17],[0,0,2,18],[0,0,2,19],[0,0,2,20],[0,0,3,0],[0,0,3,1],[0,0,3,2],[0,0,3,3],[0,0,3,4],[0,0,3,5],[0,0,3,6],[0,0,3,7],[0,0,3,8],[0,0,3,9],[0,0,3,10],[0,0,3,11],[0,0,3,12],[0,0,3,13],[0,0,3,14],[0,0,3,15],[0,0,3,16],[0,0,3,17],[0,0,3,18],[0,0,3,19],[0,0,3,20],[0,0,4,0],[0,0,4,1],[0,0,4,2],[0,0,4,3],[0,0,4,4],[0,0,4,5],[0,0,4,6],[0,0,4,7],[0,0,4,8],[0,0,4,9],[0,0,4,10],[0,0,4,11],[0,0,4,12],[0,0,4,13],[0,0,4,14],[0,0,4,15],[0,0,4,16],[0,0,4,17],[0,0,4,18],[0,0,4,19],[0,0,4,20],[0,0,5,0],[0,0,5,1],[0,0,5,2],[0,0,5,3],[0,0,5,4],[0,0,5,5],[0,0,5,6],[0,0,5,7],[0,0,5,8],[0,0,5,9],[0,0,5,10],[0,0,5,11],[0,0,5,12],[0,0,5,13],[0,0,5,14],[0,0,5,15],[0,0,5,16],[0,0,5,17],[0,0,5,18],[0,0,5,19],[0,0,5,20],[0,0,6,0],[0,0,6,1],[0,0,6,2],[0,0,6,3],[0,0,6,4],[0,0,6,5],[0,0,6,6],[0,0,6,7],[0,0,6,8],[0,0,6,9],[0,0,6,10],[0,0,6,11],[0,0,6,12],[0,0,6,13],[0,0,6,14],[0,0,6,15],[0,0,6,16],[0,0,6,17],[0,0,6,18],[0,0,6,19],[0,0,6,20],[0,0,7,0],[0,0,7,1],[0,0,7,2],[0,0,7,3],[0,0,7,4],[0,0,7,5],[0,0,7,6],[0,0,7,7],[0,0,7,8],[0,0,7,9],[0,0,7,10],[0,0,7,11],[0,0,7,12],[0,0,7,13],[0,0,7,14],[0,0,7,15],[0,0,7,16],[0,0,7,17],[0,0,7,18],[0,0,7,19],[0,0,7,20],[0,0,8,0],[0,0,8,1],[0,0,8,2],[0,0,8,3],[0,0,8,4],[0,0,8,5],[0,0,8,6],[0,0,8,7],[0,0,8,8],[0,0,8,9],[0,0,8,10],[0,0,8,11],[0,0,8,12],[0,0,8,13],[0,0,8,14],[0,0,8,15],[0,0,8,16],[0,0,8,17],[0,0,8,18],[0,0,8,19],[0,0,8,20],[0,0,9,0],[0,0,9,1],[0,0,9,2],[0,0,9,3],[0,0,9,4],[0,0,9,5],[0,0,9,6],[0,0,9,7],[0,0,9,8],[0,0,9,9],[0,0,9,10],[0,0,9,11],[0,0,9,12],[0,0,9,13],[0,0,9,14],[0,0,9,15],[0,0,9,16],[0,0,9,17],[0,0,9,18],[0,0,9,19],[0,0,9,20],[0,0,10,0],[0,0,10,1],[0,0,10,2],[0,0,10,3],[0,0,10,4],[0,0,10,5],[0,0,10,6],[0,0,10,7],[0,0,10,8],[0,0,10,9],[0,0,10,10],[0,0,10,11],[0,0,10,12],[0,0,10,13],[0,0,10,14],[0,0,10,15],[0,0,10,16],[0,0,10,17],[0,0,10,18],[0,0,10,19],[0,0,10,20],[0,0,11,0],[0,0,11,1],[0,0,11,2],[0,0,11,3],[0,0,11,4],[0,0,11,5],[0,0,11,6],[0,0,11,7],[0,0,11,8],[0,0,11,9],[0,0,11,10],[0,0,11,11],[0,0,11,12],[0,0,11,13],[0,0,11,14],[0,0,11,15],[0,0,11,16],[0,0,11,17],[0,0,11,18],[0,0,11,19],[0,0,11,20],[0,0,12,0],[0,0,12,1],[0,0,12,2],[0,0,12,3],[0,0,12,4],[0,0,12,5],[0,0,12,6],[0,0,12,7],[0,0,12,8],[0,0,12,9],[0,0,12,10],[0,0,12,11],[0,0,12,12],[0,0,12,13],[0,0,12,14],[0,0,12,15],[0,0,12,16],[0,0,12,17],[0,0,12,18],[0,0,12,19],[0,0,12,20],[0,0,13,0],[0,0,13,1],[0,0,13,2],[0,0,13,3],[0,0,13,4],[0,0,13,5],[0,0,13,6],[0,0,13,7],[0,0,13,8],[0,0,13,9],[0,0,13,10],[0,0,13,11],[0,0,13,12],[0,0,13,13],[0,0,13,14],[0,0,13,15],[0,0,13,16],[0,0,13,17],[0,0,13,18],[0,0,13,19],[0,0,13,20],[0,0,14,0],[0,0,14,1],[0,0,14,2],[0,0,14,3],[0,0,14,4],[0,0,14,5],[0,0,14,6],[0,0,14,7],[0,0,14,8],[0,0,14,9],[0,0,14,10],[0,0,14,11],[0,0,14,12],[0,0,14,13],[0,0,14,14],[0,0,14,15],[0,0,14,16],[0,0,14,17],[0,0,14,18],[0,0,14,19],[0,0,14,20],[0,0,15,0],[0,0,15,1],[0,0,15,2],[0,0,15,3],[0,0,15,4],[0,0,15,5],[0,0,15,6],[0,0,15,7],[0,0,15,8],[0,0,15,9],[0,0,15,10],[0,0,15,11],[0,0,15,12],[0,0,15,13],[0,0,15,14],[0,0,15,15],[0,0,15,16],[0,0,15,17],[0,0,15,18],[0,0,15,19],[0,0,15,20],[0,0,16,0],[0,0,16,1],[0,0,16,2],[0,0,16,3],[0,0,16,4],[0,0,16,5],[0,0,16,6],[0,0,16,7],[0,0,16,8],[0,0,16,9],[0,0,16,10],[0,0,16,11],[0,0,16,12],[0,0,16,13],[0,0,16,14],[0,0,16,15],[0,0,16,16],[0,0,16,17],[0,0,16,18],[0,0,16,19],[0,0,16,20],[0,0,17,0],[0,0,17,1],[0,0,17,2],[0,0,17,3],[0,0,17,4],[0,0,17,5],[0,0,17,6],[0,0,17,7],[0,0,17,8],[0,0,17,9],[0,0,17,10],[0,0,17,11],[0,0,17,12],[0,0,17,13],[0,0,17,14],[0,0,17,15],[0,0,17,16],[0,0,17,17]... etc.
It ends at [20,20,20,20].
I need to pick 50 combinations from the file and assign it to a variable so it would be like
var combinationsArr = [
[0,0,17,9],[0,0,17,10],[0,0,17,11],[0,0,17,12]
]; //BUT 50 of them
it's okay if it is just in order like [0,0,0,0],[0,0,0,1],[0,0,0,2],[0,0,0,3],[0,0,0,4],[0,0,0,5],[0,0,0,6],[0,0,0,7],[0,0,0,8],[0,0,0,9],[0,0,0,10],[0,0,0,11],[0,0,0,12] and doesn't have to be super random like [1,2,3,4],[9,12,13,15],[20,12,6,7]
as long as it is able to pick 50 of them.
I am doing this because 194481 combinations are a lot and makes my program carsh. so I just decided i'll put it in a text file and pick random points from the text file like from [0,0,0,1] to [0,0,0,50] OR
from [0,1,0,0] to [0,1,0,49] if that's possible.
because i have to generate a random combination. I have another array of combinations which are not supposed to be generated. Let's call it notAllowedArr.
var notAllowedArr = [
[0,0,17,9],[0,0,17,12]
];
I am thinking, i'll just generate 50 combinations and remove the ones listed in notAllowedArr then pick one from combinationsArr as the final result. I will still have to find code to remove those from combinationsArr but the result should be like.
var combinationsArr = [[0,0,17,10],[0,0,17,11]];
then i'll have a code to pick a random value from combinationsArr.
example. combinationsArr[0].
so the final result would be; [0,0,17,10]
Does anyone have a better solution?
If I understand correctly, you need to pick one random combination, which is not present in a list of forbidden combinations.
You can consider a combination of four numbers from 0 to 20 as a number from 0 to 194480 in base-21 notation. So instead of having to store all combinations in a file, we just pick a random number and convert it to base-21.
To choose a random number in a range where some values are forbidden, choose a number in the range from 0 to the maximum minus the number of forbidden values; then iterate over the forbidden values from small to large, and increment the random number every time you find a smaller or equal forbidden value.
This will make sure that every combination has the same probability of being chosen, and avoids the possibility of repeatedly choosing a forbidden combination.
function randomBase21(skip) {
var dec = [], result = [], num;
// CONVERT FORBIDDEN COMBINATIONS FROM BASE-21 TO DECIMAL AND SORT
for (var i = 0; i < skip.length; i++) {
dec[i] = skip[i][0] * 9261 + skip[i][1] * 441 + skip[i][2] * 21 + skip[i][3];
}
dec.sort(function(a, b){return a - b});
// GENERATE RANDOM NUMBER FROM 0 TO MAX - NUMBER OF FORBIDDEN COMBINATIONS
num = Math.floor(Math.random() * (194481 - skip.length));
// INCREMENT RANDOM NUMBER FOR EVERY SMALLER FORBIDDEN COMBINATION
for (var i = 0; i < skip.length && num >= dec[i]; i++) {
++num;
}
// CONVERT RANDOM NUMBER TO FOUR BASE-21 DIGITS
for (var i = 3; i >= 0; i--, num /= 21) {
result[i] = Math.floor(num % 21);
}
return result;
}
var notAllowed = [[0,0,17,9],[0,0,17,12],[20,19,17,12],[15,16,17,12]];
document.write(randomBase21(notAllowed));
Something like this should work (off the top of my head and not tested/debugged):
var samples = new Array();
for(var index = 0; index < 50; index++) {
samples.push(generatePermutation());
}
function generatePermutation() {
var result = [Math.floor(Math.random() * 20) + 1,
Math.floor(Math.random() * 20) + 1,
Math.floor(Math.random() * 20) + 1,
Math.floor(Math.random() * 20) + 1];
}
I just thought of a better way.
I think I will make a function that generates a random combination.
Then check if it exists in notAllowedArr. If it exists, it will generate another one. If not then that will return that combination :D
I think this will work faster ^^;

Why can't I use a variable created using prompt() within a function?

Below is a function which should produce a random number between two numbers which are specified by the user. The equation works if I manually specify the numbers. But if I use the prompt function it seems to produce a completely random number.
function randOm() {
var high = prompt("high");
var low = prompt("low");
return Math.floor(Math.random() * (high - low + 1)) + low;
}
document.write(randOm());
You will need to use parseFloat to convert it to a Number.
Convert the results of the prompt in numbers, because it returns strings:
return Math.floor(Math.random() * ((+high) - (+low) + 1)) + (+low);
prompt is known to return string, hence u have to convert the string to integer before performing your operations.And another disadvantage is that, if the user enters any characters like "hello" or "hi" in the prompt box, your function might return NaN, because cannot parse characters to numbers.
Script:
function randOm() {
var high = prompt("high");
var low = prompt("low");
var h=parseInt(high);
var l=parseInt(low);
return Math.floor(Math.random() * (h - l + 1)) + l;
}
document.write(randOm());
if (Number.isNaN(high) || Number.isNaN(low)){
alert ("both entries must be numbers!");
}
else{
low = parseFloat(low);
high = parseFloat(high);
return Math.floor(Math.random() * (high - low + 1)) + low;
}

Random integer in a certain range excluding one number

I would like get a random number in a range excluding one number (e.g. from 1 to 1000 exclude 577). I searched for a solution, but never solved my issue.
I want something like:
Math.floor((Math.random() * 1000) + 1).exclude(577);
I would like to avoid for loops creating an array as much as possible, because the length is always different (sometimes 1 to 10000, sometimes 685 to 888555444, etc), and the process of generating it could take too much time.
I already tried:
Javascript - Generating Random numbers in a Range, excluding certain numbers
How can I generate a random number within a range but exclude some?
How could I achieve this?
The fastest way to obtain a random integer number in a certain range [a, b], excluding one value c, is to generate it between a and b-1, and then increment it by one if it's higher than or equal to c.
Here's a working function:
function randomExcluded(min, max, excluded) {
var n = Math.floor(Math.random() * (max-min) + min);
if (n >= excluded) n++;
return n;
}
This solution only has a complexity of O(1).
One possibility is not to add 1, and if that number comes out, you assign the last possible value.
For example:
var result = Math.floor((Math.random() * 100000));
if(result==577) result = 100000;
In this way, you will not need to re-launch the random method, but is repeated. And meets the objective of being a random.
As #ebyrob suggested, you can create a function that makes a mapping from a smaller set to the larger set with excluded values by adding 1 for each value that it is larger than or equal to:
// min - integer
// max - integer
// exclusions - array of integers
// - must contain unique integers between min & max
function RandomNumber(min, max, exclusions) {
// As #Fabian pointed out, sorting is necessary
// We use concat to avoid mutating the original array
// See: http://stackoverflow.com/questions/9592740/how-can-you-sort-an-array-without-mutating-the-original-array
var exclusionsSorted = exclusions.concat().sort(function(a, b) {
return a - b
});
var logicalMax = max - exclusionsSorted.length;
var randomNumber = Math.floor(Math.random() * (logicalMax - min + 1)) + min;
for(var i = 0; i < exclusionsSorted.length; i++) {
if (randomNumber >= exclusionsSorted[i]) {
randomNumber++;
}
}
return randomNumber;
}
Example Fiddle
Also, I think #JesusCuesta's answer provides a simpler mapping and is better.
Update: My original answer had many issues with it.
To expand on #Jesus Cuesta's answer:
function RandomNumber(min, max, exclusions) {
var hash = new Object();
for(var i = 0; i < exclusions.length; ++i ) { // TODO: run only once as setup
hash[exclusions[i]] = i + max - exclusions.length;
}
var randomNumber = Math.floor((Math.random() * (max - min - exclusions.length)) + min);
if (hash.hasOwnProperty(randomNumber)) {
randomNumber = hash[randomNumber];
}
return randomNumber;
}
Note: This only works if max - exclusions.length > maximum exclusion. So close.
You could just continue generating the number until you find it suits your needs:
function randomExcluded(start, end, excluded) {
var n = excluded
while (n == excluded)
n = Math.floor((Math.random() * (end-start+1) + start));
return n;
}
myRandom = randomExcluded(1, 10000, 577);
By the way this is not the best solution at all, look at my other answer for a better one!
Generate a random number and if it matches the excluded number then add another random number(-20 to 20)
var max = 99999, min = 1, exclude = 577;
var num = Math.floor(Math.random() * (max - min)) + min ;
while(num == exclude || num > max || num < min ) {
var rand = Math.random() > .5 ? -20 : 20 ;
num += Math.floor((Math.random() * (rand));
}
import random
def rng_generator():
a = random.randint(0, 100)
if a == 577:
rng_generator()
else:
print(a)
#main()
rng_generator()
Exclude the number from calculations:
function toggleRand() {
// demonstration code only.
// this algorithm does NOT produce random numbers.
// return `0` - `576` , `578` - `n`
return [Math.floor((Math.random() * 576) + 1)
,Math.floor(Math.random() * (100000 - 578) + 1)
]
// select "random" index
[Math.random() > .5 ? 0 : 1];
}
console.log(toggleRand());
Alternatively, use String.prototype.replace() with RegExp /^(577)$/ to match number that should be excluded from result; replace with another random number in range [0-99] utilizing new Date().getTime(), isNaN() and String.prototype.slice()
console.log(
+String(Math.floor(Math.random()*(578 - 575) + 575))
.replace(/^(577)$/,String(isNaN("$1")&&new Date().getTime()).slice(-2))
);
Could also use String.prototype.match() to filter results:
console.log(
+String(Math.floor(Math.random()*10))
.replace(/^(5)$/,String(isNaN("$1")&&new Date().getTime()).match(/[^5]/g).slice(-1)[0])
);

How to get a random number in specific range using Javascript?

I'm trying to find a way to run in my Node script command that gets a random number from 0.01 to 10.85 for example. The number must look like 0.01 and not like 0.000000001.
How can I do this?
My current command:
var randomTicket = helper.getRandomInt(0, 10.85);
That command for some reason it returns only the number 0
Are there any other alternative ways?
Math.random would do the trick. It returns a value between [0,1) (1 is exclusive). Then you scale the range by the difference between max and min and add min as offset.
function getRandomArbitrary(min, max) {
return Math.random() * (max - min) + min;
}
But because you get a float value, you can not clip the decimal after the second position. You can format it to a string. I'm not sure but this should work.
var number = getRandomArbitrary(0.01, 10.85);
var numString = number.toFixed(2);
EDIT
If you only generate integers then multiply min and max by 100.0 and divide the result by 100.0.
var number = getRandomArbitrary(1.0, 1085.0);
var numString = (number / 100.0).toFixed(2);
or
var number = getRandomInt(1, 1085);
var numString = (number / 100.0).toFixed(2);

Function that accepts two numbers and returns a random number between the two numbers. (JavaScript)

Been learning JavaScript for a few weeks now, and I am trying to write a function that prompts the user for 2 numbers and the generate a random number between them. I wrote this code,
function randomInt(min,max) {
var min = prompt( "Enter a number." );
var max = prompt( "Enter another number." );
var randNum = Math.floor(Math.random() * (max - min + 1)) + min;
return randNum;
}
alert(randomInt());
It does prompt me for the numbers but it generates a random number not a number between the two that I've entered. Like I enter 5 and 20 and it returns 31 or 2 but when tried,
var min = 5;
var max = 20;
It works, actually gives me a number between 5 and 20, not sure why though. It seems like a simple task but just stumped.
The prompt() function returns strings, not numbers. You can force the values to be interpreted as numbers with the unary + operator:
var min = +prompt("Enter a number.");
var max = +prompt( "Enter another number." );
Without that, the outer + operator will preferentially perform a string concatenation operation because the right-hand operand (min) is a string. That is, in this expression:
Math.floor(Math.random() * (max - min + 1)) + min
The - operator in max - min will cause that to be done properly as a numeric subtraction. However, the outer + by which the minimum value is added back to the random number will perform a string concatenation and not a numeric addition if min is a string. Thus you'll end up with a random integer between 0 and the implied range, concatenated onto the minimum value (as a string).

Categories