如何将我的9个if语句压缩成一个

get*_*ect 47 java

我想知道所有一位数字可以分割的最小数字是什么,而不是查找它我创建了这个.

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;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

有什么建议?

rge*_*man 152

首先,您会认为您可以通过在%操作员右侧放置2到9的产品来一次测试所有这些产品.

if (i % (2 * 3 * 4 * 5 * 6 * 7 * 8 * 9) == 0)
Run Code Online (Sandbox Code Playgroud)

但由于某些数字包括其分解中的先前数字,因此您应使用较低的数字,特别是最小公倍数.8是2和4的倍数,9是3的倍数,如果产品中有8和9,则也覆盖6(2*3).

if (i % (5 * 7 * 8 * 9) == 0)
Run Code Online (Sandbox Code Playgroud)

结果是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;
Run Code Online (Sandbox Code Playgroud)

我宣布了一个常量,我会在这里使用它:

if (i % LCM_2_THRU_9 == 0)
Run Code Online (Sandbox Code Playgroud)

  • 你有点打败了练习的重点.现在你正在寻找可被2520整除的最小数字(除0之外),它是2520.但是为了获得数字2520,你必须首先进行计算. (87认同)
  • 由于`5*7*8*9`无论如何都是混淆原始逻辑,不妨只写'2520`然后*评论*它是[**最小公倍数**](https://en.wikipedia .org,wiki/Least_common_multiple)的"2,3,4,5,6,7,8,9". (58认同)
  • 你也可以建议用System.out.println替换代码(2520); (15认同)
  • @gman但那会是错的!`if(x%2 && x%4)`与`if(x%4)`相同,与`if(x%8)`不同.乘法仅适用于数字不能彼此整除的情况,如"2"和"3". (8认同)
  • 建议:声明一个常量`lcm`并添加一个注释,它是{2,3,4,5,6,7,8,9}的最小公倍数.与编译器相同,人类更容易理解. (6认同)
  • @gman然后,你会用这个常数做什么?它太大了. (5认同)

sak*_*029 84

试试这个.

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
Run Code Online (Sandbox Code Playgroud)

或者你可以把它写成一个声明.

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
Run Code Online (Sandbox Code Playgroud)

  • 如果它解释了如何提出这个代码以及代码正在做什么,这将是一个更好的答案. (46认同)
  • @ jpmc26这可能是真的但并不意味着通过添加解释不会改善答案. (10认同)
  • @DavidZ序列处理机制现在应该是常识.Java的流只是Python的列表推导和.NET的LINQ抛出的最新成员之一. (7认同)
  • 我最喜欢这个答案,因为它不依赖于检查多个模数的特定情况. (3认同)
  • @Oleksandr确实是一个修辞问题,表明你需要掌握Java lambdas的更多概念而不是python comprehrensions. (2认同)

小智 46

如前所述,编写您要做的事情的最佳方法可能是检查2到9的乘积.

但是,回答你关于如何压缩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);
}
Run Code Online (Sandbox Code Playgroud)


dis*_*ame 42

你为什么不..

反转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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

1.正如其他答案所建议的那样,也有基于语言的快捷方式.我同意他们.

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

  • 我喜欢这个,因为它不是代码问题的数学答案,花费性能成本,如果问题复杂化,不容易出现隐藏的逻辑/数学错误,并且明确的未来 - 你在六个月内不会需要阅读评论来确定你做了什么. (5认同)

pkp*_*pnd 20

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

首先,我们使用IntStream.rangeClosed(2, 9)(或等效地IntStream.range(2, 10))获得以(包括)Integer开头2和结尾的连续s 流9.我们可以boolean通过使用将此流转换为a .allMatch(...),true当且仅当每个流元素都符合某些条件时才会返回.期望标准以的形式提供lambda表达式,n -> i % n == 0.这可以用verbosely编写(Integer n) -> (i % n == 0),因此lambda表达式Integer从被调用的流中获取输入a n,并返回i(循环计数器)是否可被整除n.因此,.allMatch(n -> i % n == 0)返回trueif i可以被Integer流中的每个整除.

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

在初始化之后其值永远不会改变的变量或参数实际上是最终的.(Oracle文档)

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

这是最终的解决方案:

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


mac*_*e21 18

更简单的方法:

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

使用相同类型的结构,主要方法变为:

    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;
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)


Md *_*lam 16

什么你基本上做的是试图找到数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;
}
Run Code Online (Sandbox Code Playgroud)

如果所有数字都是互质的,那将是真的.这意味着他们没有任何共同因素.但在这种情况下,这些数字不是互质的,而且有共同的因素.像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.请参阅以下编辑以更正上述公式.

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

if ( i % 2520 == 0) { 
  System.out.println(i); 
  break;
}
Run Code Online (Sandbox Code Playgroud)

使用的另一个解决方案是简单地检查以下所有条件:

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

  • 这个答案的前提是错误的.问题是要求编写代码以找到最低公倍数,而不是检查一个数字是否可被最低公倍数整除. (5认同)
  • 问题是"我想知道所有一位数字可以分割的最小数字是什么" - 这相当于说"我想找到数字2-9的最小公倍数".然后问题的作者说"不是查找它而是创建了这个函数" - 换句话说,问题假定2-9的LCM是未知的.如果循环在2521开始,则代码将找不到LCM,因此不会实现其声明的目的. (2认同)

Fra*_*rax 12

这个问题实际上是双重的:第一部分是,如何将具有相似条件的9 if语句压缩为一些更易读的形式.另一个也许是无意识的问题是,如何将"单位数字的LCM"这样的东西添加到代码中.让我们从后者开始,然后转到下面的前者.

谷歌的结果

如果您需要这种数量你的程序(而不是程序是指计算它的唯一目的),你应该只用最简单的获得它的必要手段(在这种情况下,谷歌搜索的"最小数量由所有一个位数整除"),并在你的程序中包含一个常量,或许可以对数字来自何处进行一些评论.

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

迭代一个数组

现在这是关于压缩if语句.

有使用流的解决方案,但在您的情况下,简单的数组可能会更好.这段代码也更通用,您可以轻松地将它移植到几乎任何语言,并且它不以数字方式绑定(您可以使用任何数组).奖励点 - 任何人都应该理解它.

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());
}
Run Code Online (Sandbox Code Playgroud)

使用Streams

大多数Java-ish解决方案,这是您应该在实践中使用的 - 除非您需要非Java程序员来阅读您的代码.以saka1029和pkpnd的答案为主题,所以我不再重复了.


Yoh*_*ika 6

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

if (i % 2520 == 0) {
    System.out.println(i);
    break;
}
Run Code Online (Sandbox Code Playgroud)

  • @jbch它是最不常见的倍数,而不是总倍数.如果某些东西可以被8整除,它也可以被4和2整除. (5认同)
  • @bigsandwich是的,据我所知,答案是编辑过的.在答案之前,方程式为"1*2*3*4*5*6*7*8*9 = 2520",这显然是错误的.LCM正是他们在不抬头的情况下尝试计算的.他们没有明确说明,但A,B和C*可以分割的最小数字是A,B和C的LCM,因此对LCM进行硬编码或使用LCM函数会破坏练习的重点. (2认同)