public static int min(int a, int b, int c)
{
    int result = 0 ;
    if( a < b && a < c && b < c) result = a ;
    else if( a < b && a < c && b > c) result = a ;

    else if( a > b && a < c && b < c) result = b ;
    else if( a < b && b  > c &&  c < a) result = c ;

    else if( a > b && b < c && a > c) result = b ;
    else if( a > b && a > c && c < b) result = c ;
    return result ;
}


比嵌套的if语句好吗?有没有比这更具可读性的解决方案?对我来说,它看起来很可读,但是我不确定是否可以改进。

评论

如果if和and看起来很可读,请尝试大声阅读代码。在布法罗之前,布法罗和詹姆士在约翰内。

只是次要的,但是您可以将a
没有更多上下文,很难对此进行评估。您有理由避免使用Math.Min吗?您是否要优化比较次数?您确定不需要处理4个输入吗?

您的条件非常复杂。为什么不做类似int result = a;的事情呢? if(b <结果)结果= b;如果(c <结果)结果= c;返回结果;?这将为您提供相同的结果,并且总共具有与第一个if条件一样多的评估。与此答案的“详细”选项类似:codereview.stackexchange.com/a/58749/50461

如果先前的条件为false,您会浪费时间一次又一次地计算表达式

#1 楼


对我来说,它看起来很可读

对我来说,它不是。 />
System.out.println(min(3, 2, 2));
System.out.println(min(3, 3, 3));
System.out.println(min(1, 3, 3));
System.out.println(min(4, 2, 4));

这是因为,当您查看原始代码时,它过于复杂。
if( a < b && a < c && b < c) result = a ;
else if( a < b && a < c && b > c) result = a ;

0b < c真的重要吗?不,它不在这里。如果b > c不存在,那么这两个当前值都不成立。因此,这是一个等待等待发生的巨大错误。
因此,前两个if应该简化为:
值得到正确处理。现在也有提早退货,因此我们不需要所有这些b == c

如果我们根据返回的内容对其余的语句进行分组,则可以得到return 0: />如果始终使用<=作为第一个操作数,而完全忽略elsereturn b(同样,此处未处理b),则会得到:
if (a <= b && a <= c) return a;

由于a < ca > ca == c中的一个确实必须最小,如果两个都不是,则可以抛出异常:
else if( a > b && a < c && b < c) result = b ;
else if( a > b && b < c && a > c) result = b ;

或者,如果您不这样做,像这样的异常:
if (b <= a && b <= c) return b;

我认为这比您的原始版本要好得多。

评论


\ $ \ begingroup \ $
就个人而言,如果我按照您的方式行事,我会在发现a和b都不是正确答案后才返回c。
\ $ \ endgroup \ $
– Pimgd
2014年8月1日13:07



\ $ \ begingroup \ $
@Pimgd是的,那也是一个令人满意的解决方案。但是当使用异常时,您确实可以确定c确实必须是最小的。
\ $ \ endgroup \ $
–西蒙·福斯伯格
2014年8月1日在13:13

\ $ \ begingroup \ $
@Pimgd不,我不知道这种情况,但是如果存在这种情况(极不可能),它将抛出Exception而不是错误地返回3。
\ $ \ endgroup \ $
–西蒙·福斯伯格
2014年8月1日13:19

\ $ \ begingroup \ $
等等。 int ....保持原样,但请注意,使用浮点数可能会发生NaN ...
\ $ \ endgroup \ $
–示例
2014年8月3日,下午2:52

\ $ \ begingroup \ $
如果我们过去了,如果(a <= b && a <= c)返回a;无需返回a,我们可以安全地断言a> min(a,b,c)或等效地,min(b,c)== min(a,b,c)。因此,我们可以简化(b <= a && b <= c)返回b;的情况。如果(b <= c)返回b ;,或者甚至取消return c;并返回b <= c吗? b:c;
\ $ \ endgroup \ $
–律师
2014年8月3日在10:48

#2 楼

对于这些东西,我们有java.lang.Math

public static int min(final int a, final int b, final int c){
    return Math.min(a, Math.min(b, c));
}


哇,看它有多短!

但是今天有3个数字,明天是10个。
作为替代方案,数组又如何呢?

评论


\ $ \ begingroup \ $
第一种情况是java.util.Collections.min()。但是,它适用于集合。
\ $ \ endgroup \ $
–高
2014年8月1日在12:59

\ $ \ begingroup \ $
我实际上一直在寻找,但是后来我意识到我正在使用数组。还有另一种使用可能性!但是它使用了一个Comparator,因此即使使用Integer对象,您最终也要编写一些包装器。
\ $ \ endgroup \ $
– Pimgd
2014年8月1日13:00



\ $ \ begingroup \ $
您的第二个示例(带有数组)似乎比我现有的要复杂(请参阅我的答案)。
\ $ \ endgroup \ $
–瑞安
2014年8月1日在20:47

\ $ \ begingroup \ $
@Ryan那是因为它是\ $ O(n)\ $而不是\ $ O(2n)\ $。它更快,因为它不会首先将其转换为列表。此外,它不会自动对int进行装箱和拆箱,因此这是另一个缓解了性能的问题。
\ $ \ endgroup \ $
– Pimgd
2014年8月1日20:49



\ $ \ begingroup \ $
@Pimgd当您正确地认为它的性能较低时,我认为应该考虑可读性和可维护性。
\ $ \ endgroup \ $
–瑞安
2014年8月1日在22:21



#3 楼

我建议使用对我来说很容易理解的三元运算符:

/>
在两种情况下都将仅执行两次比较。

评论


\ $ \ begingroup \ $
我不同意三元运算符不可读。您的其他方法也很好。
\ $ \ endgroup \ $
–西蒙·福斯伯格
2014年8月1日13:11

\ $ \ begingroup \ $
@Kao也许,但是在应用程序中甚至包含少量不可读/不可维护的代码也只会产生更多相同的代码。我希望保持代码干净,易于维护且可读性强。即使更具可读性的代码导致性能下降很小,我也会很高兴受到打击,因为它会导致更强大的代码。
\ $ \ endgroup \ $
– FreeAsInBeer
2014年8月1日14:16

\ $ \ begingroup \ $
@KyleHale实际上对于问题的范围,我绝对同意FreeAsInBeer。三元本身已经是不太容易理解的方法了,然后像第一个一样,通过嵌套嵌套它们,直觉地造成了额外的混乱,这激怒了我。
\ $ \ endgroup \ $
–Vogel612♦
2014年8月1日14:38

\ $ \ begingroup \ $
我已经自由地对三元表达式进行了重新格式化,以使其更具可读性,尽管我仍然认为if-if版本更易于理解。
\ $ \ endgroup \ $
– 200_success
2014年8月1日在18:41



\ $ \ begingroup \ $
第二个也不可读。在min操作中使用>时,我必须认真思考。
\ $ \ endgroup \ $
–djechlin
2014年8月4日在1:53

#4 楼

这是我的主意:使用可选参数,并使用内置库。更清晰,更容易理解。这适用于3个参数,但也适用于任何#个参数。

public static Integer min(Integer... numbers) {
    if (numbers.length == 0) return 0;
    // wanted this: assert numbers.length > 0;, but does not work
    return Collections.min(Arrays.asList(numbers));
}


调用方式:

System.out.println(min(2,1,3)); 


给出1.

我试图找到使用泛型的解决方案,但无法使其正常工作。 >
public static Integer min(Integer... numbers) {
    if (numbers.length == 0) throw new IllegalArgumentException("Cannot have 0 arguments, i.e. min()");
    return Collections.min(Arrays.asList(numbers));
}


编辑:此解决方案有效的原因是IllegalArgumentException允许调用它的程序指定任意数量的参数(甚至为0),并且在Integer... numbers内部将其视为一个数组,我们可以使用minCollections.min找到该数组的最小值。

#5 楼

我认为它不是真正可读的,因为它传达了很多逻辑,而这根本是不需要的。

而且,根据大多数常见的Java编码标准,您也不应该在其代码中放置{换行符,在result中的;return result ;之间也应该没有空格

我建议以下内容,尽管它需要Java 8:

public static int min(final int first, final int... others) {
    return IntStream.concat(IntStream.of(first), IntStream.of(others))
        .min()
        .getAsInt();
}


以这种方式覆盖以下内容:


您允许将任意数量的整数传递给该方法。
使用Java 8,您可以清晰地获得min()流,它以某种方式检查最小值。
因为您知道至少有一个结果,所以可以安全地从OptionalInt中获取值。

一个较小的选择是IntStream.concat(IntStream.of(first), IntStream.of(others))可以构造一个IntStream很难看。

评论


\ $ \ begingroup \ $
您从哪里获得编码标准,说花括号应该与方法签名在同一行?
\ $ \ endgroup \ $
– Pimgd
2014年8月1日19:49

\ $ \ begingroup \ $
@Pimgd-我需要将三个典型的代码样式指南收集到一个地方,可能是Java标签Wiki
\ $ \ endgroup \ $
–rolfl
2014年8月1日在19:54