Java 如何将我的 9 个 if 语句浓缩为一个

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/50107150/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 23:26:34  来源:igfitidea点击:

How to condense my 9 if statements into one

java

提问by getRect

I wanted to see what the smallest number divisible by all one digit numbers was and instead of looking it up I created this.

我想看看能被所有一位数整除的最小数字是多少,而不是查找它,我创建了这个。

public static void main(String[] args) {

    for (int i = 100; i < 10000; i++) {

        if (i % 2 ==0) {

            if (i % 3 ==0) {

                if (i % 4 ==0) {

                    if (i % 5 ==0) {

                        if (i % 6 ==0) {

                            if (i % 7 ==0) {

                                if (i % 8 ==0) {

                                    if (i % 9 ==0) {

                                        System.out.println(i);

                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

As you can see, I have an if statement in an if statement x9. The code worked but I wanted to condense my if statements using an array to make my if statement like this but it didn't work.

如您所见,我在 if 语句 x9 中有一个 if 语句。该代码有效,但我想使用数组来压缩我的 if 语句以使我的 if 语句像这样,但它不起作用。

 if (i % x[1, 2, 3, 4, 5, 6, 7, 8]) {
 System.out.println(i);
 break;
 }

Any suggestions?

有什么建议?

回答by Md Johirul Islam

What you are basically doing is trying to find the number iwhich is the LCMof 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9. Initially, you may be intended simply write

什么你基本上做的是试图找到数i这是LCM2 * 3 * 4 * 5 * 6 * 7 * 8 * 9。最初,您可能打算简单地编写

if (i % (2 * 3 * 4 * 5 * 6 * 7 * 8 * 9) == 0) {
    System.out.println(i);
    break;
}

It would be true if all the numbers were coprime. That means they didn't have any common factor. But In this case, the numbers are not coprime and have common factors. Like 8 = 2*2*2, 4 = 2*2, 6 = 2*3all have 2. 3 = 1 * 3 , 6 = 2*3, 9 = 3*9all have 3. So basically we have to take the LCMof the numbers 2,3,4,5,6,7,8,9. See the following edit for correction of the above formula.

如果所有的数字都是互质的,那就是真的。这意味着它们没有任何公因子。但是在这种情况下,这些数字不是互质的并且具有公因数。就像8 = 2*2*2, 4 = 2*2, 6 = 2*3所有人都有 2。3 = 1 * 3 , 6 = 2*3, 9 = 3*9所有人都有 3。所以基本上我们必须取LCM数字的2,3,4,5,6,7,8,9。请参阅以下编辑以更正上述公式。

The LCM (Least Common Multiple) of the numbers 2,3,4,5,6,7,8,9is = 2520. So the correct formula passing all the test cases is following

数字的 LCM(最小公倍数)2,3,4,5,6,7,8,9是 = 2520。所以通过所有测试用例的正确公式如下

if ( i % 2520 == 0) { 
  System.out.println(i); 
  break;
}

Another solution to use would be simply to check all the conditions like following:

另一种使用的解决方案是简单地检查所有条件,如下所示:

if(i % 9 == 0 && i % 8 ==0 && i % 7 == 0 && i % 5 == 0) {
   System.out.println(i);
   break;
}

回答by rgettman

At first you would think you can test all of them at once by placing the product of 2 through 9 on the right side of the %operator.

起初你会认为你可以通过将 2 到 9 的乘积放在%运算符的右侧来一次测试所有这些。

if (i % (2 * 3 * 4 * 5 * 6 * 7 * 8 * 9) == 0)

But because certain numbers include previous numbers in their factorization, you should use a lower number, specifically, the least common multiple. 8 is a multiple of 2 and 4, 9 is a multiple of 3, and if 8 and 9 are in the product, then 6 (2 * 3) is covered too.

但由于某些数字在其因式分解中包含先前的数字,因此您应该使用较小的数字,特别是最小公倍数。8 是 2 和 4 的倍数,9 是 3 的倍数,如果 8 和 9 在乘积中,那么 6 (2 * 3) 也被覆盖了。

if (i % (5 * 7 * 8 * 9) == 0)

That turns out to be 2520, which is the least common multiple. It would much more readable to use 2520and explain in a comment why this number is used.

结果是 2520,这是最小公倍数。2520在评论中使用和解释为什么使用这个数字会更具可读性。

/**
 * The goal is to test if the number is a multiple of all integers
 * from 2 through 9.  Mathematically, the least common multiple to is a
 * multiple of all its input numbers.  Here, the LCM of 2, 3, ..., 9 is 2520.
 */
public static final int LCM_2_THRU_9 = 2520;

I've declared a constant and I'll use it here:

我已经声明了一个常量,我将在这里使用它:

if (i % LCM_2_THRU_9 == 0)

回答by stoAlias

As previously answered probably the neatest way to write what you are trying to do is to check for the product of 2 through 9.

如前所述,编写您正在尝试做的事情的最简洁方法可能是检查 2 到 9 的乘积。

However, to answer your question on how you can condense if statements; nested if statements are equivalent to the logical operator AND, hence you could also write your if statements in the following manner:

但是,要回答有关如何压缩 if 语句的问题;嵌套的 if 语句等效于逻辑运算符 AND,因此您也可以按以下方式编写 if 语句:

if (i % 2 == 0 && i % 3 == 0 && i % 4 == 0 && i % 5 == 0 && i % 6 == 0 && i % 7 == 0 && i % 8 == 0 && i % 9 == 0) {
System.out.println(i);
}

回答by saka1029

Try this.

尝试这个。

for (int i = 100; i < 10000; ++i) {
    int x = i;
    if (IntStream.of(2, 3, 4, 5, 6, 7, 8, 9).allMatch(k -> x % k == 0)) {
        System.out.println(i);
        break;
    }
}

-> 2520

Or you can write this as one statement.

或者你可以把它写成一个语句。

int result = IntStream
    .range(100, 10000)
    .filter(i -> IntStream.of(2, 3, 4, 5, 6, 7, 8, 9).allMatch(k -> i % k == 0))
    .findFirst()
    .getAsInt();

System.out.println(result);

-> 2520

回答by Yohan Malshika

I think you can use LCM (Least Common Multiple)of (1, 2, 3, 4, 5, 6, 7, 8, 9) = 2520, like this:

我认为您可以使用(1, 2, 3, 4, 5, 6, 7, 8, 9) = 2520 的LCM(最小公倍数),如下所示:

if (i % 2520 == 0) {
    System.out.println(i);
    break;
}

回答by pkpnd

In Java 8 onwards, you can use a Streamapproach (specifically using IntStream).

在 Java 8 之后,您可以使用Stream方法(特别是使用IntStream)。

First, we use IntStream.rangeClosed(2, 9)(or equivalently, IntStream.range(2, 10)) to obtain a stream of consecutive Integers starting with 2and ending with 9(inclusive). We can turn this stream into a booleanby using .allMatch(...), which returns trueif and only if every stream elementmatches some criteria. The desired criteria is provided in the form of a lambda expression, n -> i % n == 0. This can be written verbosely as (Integer n) -> (i % n == 0), so the lambda expression takes as input an Integerfrom the stream called n, and returns whether i(the loop counter) is divisible by n. Hence, .allMatch(n -> i % n == 0)returns trueif iis divisible by every Integerin the stream.

首先,我们使用IntStream.rangeClosed(2, 9)(或等效地,IntStream.range(2, 10))获取以(包括)Integer开头2和结尾的连续s流9。我们可以boolean使用 using将这个流转换为 a .allMatch(...)true当且仅当每个流元素都匹配某些条件时才返回。期望标准以的形式提供lambda表达式n -> i % n == 0。这可以详细写为(Integer n) -> (i % n == 0),因此 lambda 表达式将Integer来自称为 的流的an 作为输入n,并返回i(循环计数器)是否可被 整除n。因此,如果可以被流中的each 整除,则.allMatch(n -> i % n == 0)返回。trueiInteger

We need to make one more modification: variables used in lambda expressions (such as i) must be effectively final:

我们需要再做一项修改:在 lambda 表达式中使用的变量(例如i)必须是有效的 final

A variable or parameter whose value is never changed after it is initialized is effectively final. (Oracle documentation)

其值在初始化后永远不会改变的变量或参数实际上是最终的。(甲骨文文档

However, the loop counter iis noteffectively final, since it gets incremented (thus reassigned) every iteration. The solution is to declare a new variable int x = i;inside the loop, so that xis only assigned once within its scope (that is, one iteration of the loop). Hence, xis effectively finaland can be used in the lambda expression.

然而,循环计数器i实际上并不是最终的,因为它每次迭代都会增加(因此重新分配)。解决方案是int x = i;在循环内声明一个新变量,以便x在其范围内只分配一次(即循环的一次迭代)。因此,x实际上是最终的,可以在 lambda 表达式中使用。

Here's the final solution:

这是最终的解决方案:

import java.util.stream.IntStream;

public static void main(String[] args) {
    for (int i = 100; i < 10000; i++) {
        int x = i; // x is effectively final
        if (IntStream.rangeClosed(2, 9).allMatch(n -> x % n == 0)) {
            System.out.println(i);
            break;
        }
    }
}

回答by mackycheese21

Much simpler way:

更简单的方法:

    public static boolean isDivisible(int number) {
        for (int i = 2; i <= 9; i++) {
            if (num % i != 0) {
                return false;
            }
        }
        return true;
    }

And using the same type of structure, main method becomes:

并使用相同类型的结构,main方法变为:

    public static void main(String[] args) {
        for (int i = 100; i <= 100000; i++) {
            if (isDivisible(i)) {
                System.out.println("Divisible by numbers 2...9: " + i);
                break;
            }
        }
    }

回答by Frax

The question in actually two-fold: first part is, how to compress 9 if statements with similar condition to some more readable form. The other, perhaps unintended question is, how should things like "LCM of single-digit numbers" be added to the code. Let's start with the latter , and go to former below.

实际上有两个问题:第一部分是,如何将具有相似条件的 9 个 if 语句压缩为更易读的形式。另一个可能是意想不到的问题是,如何将“一位数的 LCM”之类的内容添加到代码中。让我们从后者开始,然后转到下面的前者。

Google for the result

谷歌搜索结果

If you need this kind of number inyour program (instead of the sole purpose of program being computing it), you should just obtain it by the simplest means necessary (in this case, googling for "smallest number divisible by all one digit numbers"), and include in your program as a constant, perhaps with some comment about where the number came from.

如果您需要这种数量你的程序(而不是程序是指计算它的唯一目的),你应该通过必要的最简单的方法(在这种情况下获得的,“所有一个数字编号最小的数整除” google搜索),并将其作为常量包含在您的程序中,也许对数字的来源有一些评论。

If you can't just find it, try computing it yourself (like rgettman did), and again include it as constant. If that fails or takes too much time, write one-off program to compute the number, but don't make it a part of the bigger program using the constant. It's a good idea to store the one-off code somewhere, though. A comment may be the right place.

如果您无法找到它,请尝试自己计算它(就像 rgettman 所做的那样),然后再次将其作为常量包含在内。如果失败或花费太多时间,请编写一次性程序来计算该数字,但不要使用常量将其作为更大程序的一部分。不过,将一次性代码存储在某处是个好主意。评论可能是正确的地方。

Iterate over an array

遍历数组

Now that's about compressing the if statement.

现在是关于压缩 if 语句。

There were solutions using streams, though in your case a simple array may be better. This code is also more generic, you can port it to almost any language with minimal effort, and it's not tied in iny way to numbers (you can use an array of anything). Bonus point - anyone should understand it.

有使用流的解决方案,但在您的情况下,简单的数组可能更好。这段代码也更通用,您可以毫不费力地将其移植到几乎任何语言,并且它与数字没有任何联系(您可以使用任何数组)。加分点 - 任何人都应该理解它。

static boolean divisibleByAll(int n, int[] divisors) {
    for (int d : divisors) {
        if (n % d != 0) {
            return false;
        }
    }
    return true;
}

static int lcmOfSingleDigits() {
    int[] divisors = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    for (int i = 100; i < 10000; i++) {
        if (divisibleByAll(i, divisors)) {
            return i;
        }
    }
    return -1;  // Perhaps better to throw an exception
}

public static void main(String args[]) {
    System.out.println("Smallest number divisible by all one digit numbers: " +
                       lcmOfSingleDigits());
}

Use Streams

使用流

Most Java-ish solution, that's what you should use in practice - unless you need non-Java programmers to read your code. Covered by saka1029's and pkpnd's answers, so I won't repeat it.

大多数 Java 风格的解决方案,这就是您在实践中应该使用的解决方案 - 除非您需要非 Java 程序员来阅读您的代码。saka1029's 和 pkpnd's 的答案都涵盖了,所以我不会重复。

回答by zwol

What you are trying to do, as several other people have mentioned, is compute the least common multipleof the numbers 1, 2, 3, ..., 9.

正如其他几个人所提到的,您要做的是计算数字 1、2、3、...、9 的最小公倍数

But how do you do that in a computer? First, you need to know how to compute the greatest common divisorof two numbers:

但是你如何在电脑上做到这一点呢?首先,您需要知道如何计算两个数的最大公约数

function gcd2(a, b)
    while b ≠ 0
        t := b; 
        b := a mod b; 
        a := t; 
    return a;

Now, the least common multiple of twonumbers can be computed from their greatest common divisor with a simple formula:

现在,两个数的最小公倍数可以用一个简单的公式从它们的最大公约数计算出来:

function lcm2(a, b)
    if a = 0 and b = 0
        return 0;
    else
        return abs(a*b) / gcd2(a,b);

(The special case for a and b both being zero is necessary to avoid division by zero.)

(a 和 b 都为零的特殊情况是避免被零除的必要条件。)

And finally, LCM(a,b,c) = LCM(LCM(a,b),c), so to compute the LCM of more than two numbers, iterate over a list:

最后,LCM(a,b,c) = LCM(LCM(a,b),c)为了计算两个以上数字的 LCM,迭代一个列表:

function lcmN(ns)
    let rv := 1;
    for n in ns
        rv := lcm2(rv, n);
    return rv;

Translation of pseudocode to Java is left as an exercise.

将伪代码翻译成 Java 留作练习。

回答by displayName

Why don't you..

你为什么不..

Invert the IFs?

反转IF?



public static void main(String[] args) {

    for (int i = 100; i < 10000; i++) {

        //If value is not valid, continue to next value
        if (i % 2 != 0) continue;
        if (i % 3 != 0) continue;
        if (i % 4 != 0) continue;
        if (i % 5 != 0) continue;
        if (i % 6 != 0) continue;
        if (i % 7 != 0) continue;
        if (i % 8 != 0) continue;
        if (i % 9 != 0) continue;

        //Valid value found. Print and break out of the loop.
        System.out.println(i);
        break;
    }
}


Alternatively, the above code can be refactored further to:

或者,上述代码可以进一步重构为:

public static void main(String[] args) {
    for (int i = 100; i < 10000; i++) {
        if (isPrintable(i)) {
            System.out.println(i);
            break;
        }
    }
}

private static boolean isPrintable(int value) {
    return value % 2 == 0
           && value % 3 == 0
           && value % 4 == 0
           && value % 5 == 0
           && value % 6 == 0
           && value % 7 == 0
           && value % 8 == 0
           && value % 9 == 0;
}


Further, per @TeePeemm's suggestion, isPrintable()can be reduced to:

此外,根据@TeePeemm 的建议,isPrintable()可以简化为:

private static boolean isPrintable(int value) {
    for (int divisor = 2; divisor < 10; divisor++) {
        if (value % divisor != 0) return false;
    }
    return true;
}


1. There are language based shortcuts too, as suggested in other answers. I agree with them.

1. 也有基于语言的快捷方式,如其他答案中所建议。我同意他们的观点。

2. A lot of answers used the LCM of the numbers for making the code concise, but that is a dormant bug waiting to bite. The loop execution completely changes which can be seen by commenting out the break;. The seemingly simple solution introduces a subtle, potential bug.

2. 很多答案使用数字的 LCM 来使代码简洁,但这是一个等待咬的休眠错误。循环执行完全改变,这可以通过注释掉break;. 看似简单的解决方案引入了一个微妙的潜在错误。