随机数,不等于前一个数字
我需要得到随机数字,但不应该等于以前的数字。 这是我的一段代码。 但它不起作用。
function getNumber(){ var min = 0; var max = 4; var i; i = Math.floor(Math.random() * (max - min)) + min; if (i=== i) { i = Math.floor(Math.random() * (max - min)) + min; } return i; }; console.log(getNumber());
这个答案提出了三个尝试
-
一个具有
getNumber
函数属性的简单版本,last
存储最后一个随机值。 -
如果
max
小于min
则在min
和max
使用闭包,并引发exception。 -
这个版本结合了闭包和保留所有随机值的想法,并且使用它看起来是合适的。
一
您可以使用getNumber
属性来存储最后一个数字,并使用do ... while
循环。
function getNumber() { var min = 0, max = 4, random; do { random = Math.floor(Math.random() * (max - min)) + min; } while (random === getNumber.last); getNumber.last = random; return random; }; var i; for (i = 0; i < 100; i++) { console.log(getNumber()); }
.as-console-wrapper { max-height: 100% !important; top: 0; }
下面的方法在[min,max]范围内生成一个新的随机数,并确保这个数字不同于前一个数字,没有循环,也没有recursion调用( Math.random()
只被调用一次):
- 如果以前的号码存在,减less最多一个
- 在范围内生成一个新的随机数
- 如果新号码等于或大于前一号码,请添加一个
(另一种方法:如果新的号码等于上一个号码,则将其设置为最大值+ 1)
为了将前一个数字保留在闭包中,可以在IIFE中创buildgetNumber
:
// getNumber generates a different random number in the inclusive range [0, 4] var getNumber = (function() { var previous = NaN; return function() { var min = 0; var max = 4 + (!isNaN(previous) ? -1 : 0); var value = Math.floor(Math.random() * (max - min + 1)) + min; if (value >= previous) { value += 1; } previous = value; return value; }; })(); // Test: generate 100 numbers for (var i = 0; i < 100; i++) { console.log(getNumber()); }
.as-console-wrapper { max-height: 100% !important; top: 0; }
在这个线程中的大部分答案都过于复杂。
下面是一个简单的例子,我将如何做到这一点:
function getNumber(){ return (getNumber.number = Math.floor(Math.random() * (4 + 1))) === getNumber.lastNumber ? getNumber() : getNumber.lastNumber = getNumber.number; } console.log(getNumber()); // Generates a random number between 0 and 4
现场示例: https : //jsfiddle.net/menv0tur/3/
从一开始就从一组可能值中删除以前的值。
function getNumber(previous) { var numbers = [0, 1, 2, 3, 4]; if (previous !== undefined) { numbers.splice(numbers.indexOf(previous), 1); } var min = 0; var max = numbers.length; var i; i = Math.floor(Math.random() * (max - min)) + min; return numbers[i]; }; //demonstration. No 2 in a row the same var random; for (var i = 0; i < 100; i++) { random = getNumber(random); console.log(random); }
首先函数应该和以前的值比较,现在我们只有i
自己比较的variables。 为了确保我们没有以前的价值,我们需要循环内部(在我的解决schemerecursion),因为单个if statement
不能确定第二个随机将不会是相同的(存在的机会)。 你的号码是非常小的,所以碰撞的几率很高,有可能这个循环需要很less的执行。
function getNumber(prev){ var min = 0; var max = 4; var next; next = Math.floor(Math.random() * (max - min)) + min; if (next===prev) { console.log("--run recursion. Our next is ="+next); //log only for test case next = getNumber(prev); //recursive } return next; }; //test 100 times var num=0; for ( var i=0; i<100; i++){ num=getNumber(num); console.log(num); }
您将需要一个比getNumber
函数本地variables范围更大的variables。 尝试:
var j; function getNumber(){ var min = 0; var max = 4; var i = Math.floor(Math.random() * (max - min)) + min; if (j === i) { i = getNumber(); } j = i; return i; };
您可以使用@NinaScholz模式的实现,其中前一个值作为调用函数的属性存储,用条件逻辑代替递增或递减循环的当前返回值。
如果当前值等于之前返回的值,则当前值在当前函数调用期间被改变,而不使用循环或recursion,在返回改变的值之前。
var t = 0; function getNumber() { var min = 0, max = 4, i = Math.floor(Math.random() * (max - min)) + min; console.log(`getNumber calls: ${++t}, i: ${i}, this.j: ${this.j}`); if (isNaN(this.j) || this.j != i) { this.j = i; return this.j } else { if (this.j === i) { if (i - 1 < min || i + 1 < max) { this.j = i + 1; return this.j } if (i + 1 >= max || i - 1 === min) { this.j = i - 1; return this.j } this.j = Math.random() < Math.random() ? --i : ++i; return this.j } } }; for (var len = 0; len < 100; len++) { console.log("random number: ", getNumber()); }
一般的解决scheme
跟踪最后生成的数字。 当生成一个新号码时,请检查它是否与最后一个不同。 如果不是,请继续生成新的数字,直到它不同,然后输出它。
工作演示
var getNumber = (function(){ var min = 0; var max = 4; var last = -1; return function(){ var current; do{ // draw a random number from the range [min, max] current = Math.floor(Math.random() * (max + 1 - min)) + min; } while(current === last) return (last = current); } })(); // generate a sequence of 100 numbers, // see that they all differ from the last for(var test = [], i = 0; i < 100; i++){ test[i] = getNumber(); } console.log(test);
此解决scheme使用ES6生成器,避免生成随机数字,直到find符合前提条件的数字(两个相关的数字必须不同)。
主要想法是有一个数组和索引数组。 然后你得到一个随机的索引(为了符合前提条件,索引的数组将是用先前select的索引过滤索引数组的结果)。 返回值将是对应于数字数组中索引的数字。
function* genNumber(max = 4) {// Assuming non-repeating values from 0 to max let values = [...Array(max).keys()], indexes = [...Array(max).keys()], lastIndex, validIndexes; do { validIndexes = indexes.filter((x) => x !== lastIndex); lastIndex = validIndexes[Math.floor(Math.random() * validIndexes.length)]; yield values[lastIndex]; } while(true); } var gen = genNumber(); for(var i = 0; i < 100; i++) { console.log(gen.next().value); }
如果你想检查结果,这里是小提琴 。
将以前生成的随机数保存在一个数组中检查新的数字与现有的数字,你可以防止重复的随机数生成。
// global variables tot_num = 10; // How many number want to generate? minimum = 0; // Lower limit maximum = 4; // upper limit gen_rand_numbers = []; // Store generated random number to prevent duplicate. /*********** **This Function check duplicate number** ****************/ function in_array(array, el) { for (var i = 0; i < array.length; i++) { if (array[i] == el) { return true; } } return false; } /*--- This Function generate Random Number ---*/ function getNumber(minimum, maximum) { var rand = Math.floor(Math.random() * (maximum - minimum + 1)) + minimum; if (gen_rand_numbers.length <= (maximum - minimum)) { if (!in_array(gen_rand_numbers, rand)) { gen_rand_numbers.push(rand); //alert(rand) console.log(rand); return rand; } else { return getNumber(minimum, maximum); } } else { alert('Final Random Number: ' + gen_rand_numbers); } } /*--- This Function call random number generator to get more than one random number ---*/ function how_many(tot_num) { for (var j = 0; j < tot_num; j++) { getNumber(minimum, maximum); } }
<script src = "https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js" > </script> <input type = "button" onclick = "how_many(4)" value = "Random Number" >
您可以使用线性同余生成器的扩展实现。
一个线性同余发生器(LCG)是一个algorithm,产生一个伪随机数序列计算一个不连续的分段线性方程。
以下函数返回一个种子随机数与最小值和最大值的关系:
Math.seededRandom = function(seed, min, max) { max = max || 1; min = min || 0; // remove this for normal seeded randomization seed *= Math.random() * max; seed = (seed * 9301 + 49297) % 233280; let rnd = seed / 233280.0; return min + rnd * (max - min); };
在你的情况下,因为你不希望新的号码与以前相同,那么你可以传递以前生成的号码作为种子。
下面是一个例子,它产生了100个随机数字:
Math.seededRandom = function(seed, min, max) { max = max || 1; min = min || 0; // remove this for normal seeded randomization seed *= Math.random() * max; seed = (seed * 9301 + 49297) % 233280; let rnd = seed / 233280.0; return min + rnd * (max - min); }; let count = 0; let randomNumbers = []; let max = 10; do { let seed = (randomNumbers[randomNumbers.length -1] || Math.random() * max); randomNumbers.push(Math.seededRandom(seed, 0, max)); count++; } while (count < 100) console.log(randomNumbers);
一个有趣的答案,在一行中生成从0到4的数字:
console.log(Math.random().toString(5).substring(2).replace(/(.)\1+/g, '$1').split('').map(Number));
function getNumber(){ var min = 0; var max = 4; var i; i = Math.floor(Math.random() * (max - min)) + min; while(i==getNumber.last) i = Math.floor(Math.random() * (max - min)) + min; getNumber.last=i; return i; }; console.log(getNumber());
尝试这个
var prev_no = -10; function getNumber(){ var min = 0; var max = 4; var i; i = Math.floor(Math.random() * (max - min)) + min; while (i == prev_no) { i = Math.floor(Math.random() * (max - min)) + min; prev_no = i; } return i; }; console.log(getNumber());
你可以使用Promise
, Array.prototype.forEach()
, setTimeout
。 创build并迭代一个数组,其中.length
设置为max
; 在duration
设置为随机值的.forEach()
callback中使用setTimeout
,以便将数组的索引推送到新数组,以便在新数组内对索引进行非均匀分配。 从getNumber
函数返回已解决的Promise
,其中.forEach()
处的Promise
值将是.length
的数组,其中.forEach()
callback中的随机index
作为没有重复条目的值。
function getNumber(max) { this.max = max; this.keys = []; this.arr = Array.from(Array(this.max)); this.resolver = function getRandom(resolve) { this.arr.forEach(function each(_, index) { setTimeout(function timeout(g) { g.keys.push(index); if (g.keys.length === g.max) { resolve(g.keys) }; }, Math.random() * Math.PI * 100, this); }, this) }; this.promise = new Promise(this.resolver.bind(this)); } var pre = document.querySelector("pre"); var random1 = new getNumber(4); random1.promise.then(function(keys) { pre.textContent += keys.length + ":\n"; keys.forEach(function(key) { pre.textContent += key + " "; }) }); var random2 = new getNumber(1000); random2.promise.then(function(keys) { pre.textContent += "\n\n"; pre.textContent += keys.length + ":\n"; keys.forEach(function(key) { pre.textContent += key + " "; }) });
pre { white-space: pre-wrap; width: 75vw; }
<pre></pre>
除非您执行数据库查询来检查新号码的存在,否则无法实现此目的。 如果存在,重复该过程。
有一个build筑的可能性,使得唯一的随机数是产生两个随机数,并结合string。
例如:
rand_num1 = rand(5); rand_num2 = rand(4);
然后结合rand_num1和rand_num2,这更像是独特的
实际例子:
(23456)(2345) (23458)(1290) (12345)(2345)
也增加数字的数量来减less重复。