跳出语句不会中断循环。

5

我想设置两个数字(n1和n2)的最小公倍数,但我的break语句不起作用。我不想使用return(它可以工作)。有没有一种方法可以解决这个问题?谢谢。

var firstDayTogether,n1,n2;

for(var i=1;i<12345;i++){
    for(var j=1;j<12345;j++){
        if((s1*i)==(s2*j)){
            firstDayTogether=(s1*i);
            break;
        }
    }
}

7
break语句只能中断一个循环。 - jyvet
你有嵌套循环,你想同时跳出两个循环吗? - Saqib Amin
break语句只会跳出当前的for循环。如果你想要跳出外层的循环,可以使用return语句...或者通过检查条件并再次使用break来中断第二个for循环。 - Rash
5
以下是翻译的内容:有关在 JavaScript 中如何跳出嵌套循环的最佳方式。 - dtanders
2
我认为你应该使用更高效的算法:https://zh.wikipedia.org/wiki/%E6%9C%80%E5%B0%8F%E5%85%AC%E5%80%8D%E6%95%B0 - Fabricator
3个回答

21

你只是在中断内部循环。你可以使用标签来指定要结束的循环。

outerloop: for( var i=1; i<12345; i++) {
    for( var j=1; j<12345; j++) {
        if((s1*i)==(s2*j)) {
            firstDayTogether = s1*i;
            break outerloop; // <== !!
        }
    }
}

1
这太酷了。你能加一些解释说明它是做什么的/如何工作吗? - random_user_name
1
很久以前就没在JavaScript中看到标签了。+1 - AtheistP3ace
1
我不知道为什么“很长时间没有看到某物”会得到+1:通常,没有看到某物意味着有更好的选择... 话虽如此,它确实解释了问题并提供了一个最小化的解决方案(这可能是最合适的)。 - user2864740
1
先生,既然您有兴趣,那我来解释一下。它们是两件不同的事情。我喜欢他的回答。我评论了我很久没有见到的东西。 - AtheistP3ace
1
这个标记概念非常棒。我按照你的步骤操作,并发现了一个参考链接,如果有人对此更深入地了解感兴趣: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/label - Ming Huang

2

正如评论中所指出的,break只能跳出当前循环,无法跳出嵌套循环的外层循环。

将嵌套循环放入函数中,然后在找到结果时自然可以返回。

var firstDayTogether,n1,n2;

function findFirst(s1, s2) {
    for(var i=1;i<12345;i++){
        for(var j=1;j<12345;j++){
            if((s1*i)==(s2*j)){
                return (s1*i);
            }
        }
    }
}

firstDayTogether = findFirst(n1, n2);

虽然“answer”标签很好,但我更喜欢这个答案。 - random_user_name

1
有办法让这更有效率:
  • The first one is to directly test for divisibility, n2 has to be a divisor of the LCM n1*i, so that there is only one loop and no label needed:

    for ( var i=1; i<12345; i++) {
        if((n1*i) % n2 == 0) {
            firstDayTogether = n1*i;
            break;
        }
    }
    
  • The second improvement is to apply mathematics in that

    LCM(n1,n2) = n1·n2 / GCD(n1,n2)

    and for the GCD you can use your preferred variant of Euclids algorithm.

    var a=n1;
    var b=n2;
    while(b!=0){ var r=a%b; a=b; b=r; }
    firstDayTogether = n1*n2/a; 
    

第一个变体更短,没有换行:

    var i;
    for (i=1; (n1*i) % n2 != 0; i++) { }
    firstDayTogether = n1*i;

1
你最后的代码片段输出的结果与第一个不同。 最后的代码应该更改为:var i; for (i=1; (n1*i) % n2 != 0; i++) { } firstDayTogether = n1*i; - morido
你是对的,结果包含LCM之前的一步。使用另一种变体进行编辑。 - Lutz Lehmann
在你的修改之后,它并没有变得更好。考虑 n1 == n2 的情况。而且为什么你实际上必须一直在循环体内重新分配 firstDayTogether?中间结果并不重要(并且与你的效率目标相矛盾)。 - morido
现在,在第一次迭代中,您的条件本质上是读作0%n2!= 0,无论n2的值如何,它都为始终为假。换句话说:仍然不起作用。其实将i放在循环外面有什么不好的呢? 在ANSI C中,这是正常的方式... - morido
你一定要发出那么多负面的能量吗?在它变得太荒谬之前,我会采纳你现在更简单的解决方案。 - Lutz Lehmann
显示剩余3条评论

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