在Javascript中的简单递归

3

我想编写一个函数来检查随机数是否等于之前的随机数,并返回一个新的随机数,不等于之前的随机数。我想使用递归来实现这个功能,但我不确定语法是否正确。

function newNumber(next,previous) {
    if (next != previous)
        return next;
    else {
        next = Math.floor(Math.random()*10);
        newNumber(next, previous);
    }
}

什么是使它工作的最佳方法?

不,递归不是在这里正确的方法。当不需要时,不要过度使用递归。 - gdoron
1
你想将这个数字与所有之前使用过的随机数进行比较,还是只与上一个返回的随机数进行比较——也就是说,你不希望这个新数字连续两次返回相同的数字。 - Alan
我希望该函数始终显示与先前值的比较中的新值。 - Emanegux
4个回答

7
我建议完全放弃使用递归。只需将上一个随机数存储为函数本身的属性,下一次用户需要随机数时,返回第一个与上一个不同的计算结果即可。
类似以下代码实现:
function newNumber() {
    var nextValue;
    while ((nextValue = Math.floor(Math.random()*10)) === newNumber.previous) ;

    newNumber.previous = nextValue;
    return nextValue;
}

附带问题:使用属性还是闭包更好? - Alan
@Alan - 闭包只是一种花哨的说法,意思是函数“记住”了它创建时存在的上下文(“激活上下文”)。它与递归并不是一种二选一的关系,而且据我所知,在这里并不适用。 - Adam Rackis
@Alan:两种情况都是有效的。不过我会使用“闭包”,因为它不会让previous在函数作用域之外可用。此外,这样可以更容易地独立构建多个计算随机数的函数(这样来自其他无关调用的最后一个值就不会被当作你的调用的最终结果)。 - Tadeck
@alan 和 gdoron - 使用闭包的另一个优点是没有其他人可以干扰先前的值 - 你得到了一种模拟的“私有”。 - Adam Rackis
1
@AdamRackis,理论上是这样的。但实际上并不重要,除非你想改变它,否则没有人会去做。这个私人问题更多的是一种偏执症而不是真正的威胁... :) - gdoron
显示剩余3条评论

3

闭包方式:

var newNumber = (function () {
    var previous;

    return function () {
        var nextValue;
        while ((nextValue = Math.floor(Math.random() * 10)) === previous);

        previous = nextValue;
        return nextValue;
    };
})();

Fiddle


@AdamRackis,我有点复制了你的代码并将其适应闭包,所以它可能看起来很熟悉... :) - gdoron

3
你不需要使用递归来实现这个。事实上,你甚至不需要循环。只需从不与前一个数字相同的数字中随机选择一个即可:
function newNumber(previous) {
  var next = Math.floor(Math.random()*9);
  if (next >= previous) next++;
  return next;
}

1
现在它不再是随机的了。获得“previous+1”的概率更高 :D - Arjun
这只是错误的随机实现,你可以使用for循环并跳过Math.random...我相信他不想存储先前的值。 - gdoron
正如我和阿尔君之前所写的,1. 得到前一个数字加1的概率比其他数字更大。2. 你必须存储前一个数字才能使其工作,这似乎不是他想要的。你真的认为这是一个随机数生成器吗? - gdoron
@gdoron:1. 你错了。获取 previous+1 的机会并不更大。看代码!2. 在原始代码中,操作符将前一个数字发送到函数中,为什么你认为这不是他想要做的? - Guffa
  1. 一个展示问题的演示
  2. 你说得对,我被Adam的回答搞混了,我看了一下,甚至复制了主要函数,所以忘记了起点,我道歉!
- gdoron
@gdoron:那个演示根本没有展示你所声称的内容,而且它也不能正常工作。这里是一个已经修正过的版本:http://jsfiddle.net/Guffa/MXHqJ/1/ 然而,它只计算了特定数字的出现次数,并没有将它们与前一个数字进行比较。这里有一个演示,实际上进行了比较,并证明了没有这样的问题:http://jsfiddle.net/Guffa/MXHqJ/2/ - Guffa

1

else块中,只需添加returnnewNumber(next, previous);即可。现在的代码如下:

function newNumber(next,previous) {
    if (next != previous)
        return next;
    else {
        next = Math.floor(Math.random()*10);
        return newNumber(next, previous);
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接