简体   繁体   English

查找3个数字中最小的Java的最有效方法?

[英]Most efficient way to find smallest of 3 numbers Java?

I have an algorithm written in Java that I would like to make more efficient.我有一个用 Java 编写的算法,我想让它更高效。 A part that I think could be made more efficient is finding the smallest of 3 numbers.我认为可以提高效率的一个部分是找到 3 个数字中最小的一个。 Currently I'm using the Math.min method as below:目前我正在使用Math.min方法如下:

double smallest = Math.min(a, Math.min(b, c));

How efficient is this?这有多有效? Would it be more efficient to replace with if statements like below:用下面的 if 语句替换是否更有效:

double smallest;
if (a <= b && a <= c) {
    smallest = a;
} else if (b <= c && b <= a) {
    smallest = b;
} else {
    smallest = c;
}

Or if any other way is more efficient或者如果任何其他方式更有效

I'm wondering if it is worth changing what I'm currently using?我想知道是否值得改变我目前使用的东西?

Any speed increase would be greatly helpful任何速度增加都会非常有帮助

For a lot of utility-type methods, the apache commons libraries have solid implementations that you can either leverage or get additional insight from.对于许多实用程序类型的方法,apache 公共库具有可靠的实现,您可以利用它们或从中获得更多见解。 In this case, there is a method for finding the smallest of three doubles available in org.apache.commons.lang.math.NumberUtils.在这种情况下,有一种方法可以找到 org.apache.commons.lang.math.NumberUtils 中可用的三个双精度数中最小的一个。 Their implementation is actually nearly identical to your initial thought:它们的实现实际上与您最初的想法几乎相同:

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

No, it's seriously not worth changing.不,这真的值得改变。 The sort of improvements you're going to get when fiddling with micro-optimisations like this will not be worth it.在摆弄像这样的微优化时,您将获得的那种改进是不值得的。 Even the method call cost will be removed if the min function is called enough.如果min函数被调用得足够多,甚至方法调用成本也会被移除。

If you have a problem with your algorithm, your best bet is to look into macro-optimisations ("big picture" stuff like algorithm selection or tuning) - you'll generally get much better performance improvements there.如果你有你的算法有问题,最好的办法是寻找到宏观的优化(“大局”的东西一样算法选择或调整) -你通常会得到更好的性能改进存在。

And your comment that removing Math.pow gave improvements may well be correct but that's because it's a relatively expensive operation.您认为删除Math.pow带来改进的评论很可能是正确的,但那是因为这是一项相对昂贵的操作。 Math.min will not even be close to that in terms of cost. Math.min在成本方面甚至不会接近。

double smallest = a;
if (smallest > b) smallest = b;
if (smallest > c) smallest = c;

Not necessarily faster than your code.不一定比你的代码快。

Let me first repeat what others already said, by quoting from the article "Structured Programming with go to Statements" by Donald Knuth:让我首先重复其他人已经说过的话,引用唐纳德·克努斯 (Donald Knuth) 的文章“带 go to 语句的结构化编程”:

We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil.我们应该忘记小效率,比如大约 97% 的时间:过早的优化是万恶之源。

Yet we should not pass up our opportunities in that critical 3%.然而,我们不应该错过关键的 3% 的机会。 A good programmer will not be lulled into complacency by such reasoning, he will be wise to look carefully at the critical code;一个优秀的程序员不会被这样的推理所迷惑,他会明智地仔细查看关键代码; but only after that code has been identified.但只有在识别出该代码之后。

(emphasis by me) (我强调)

So if you have identified that a seemingly trivial operation like the computation of the minimum of three numbers is the actual bottleneck (that is, the "critical 3%") in your application, then you may consider optimizing it.所以,如果你已经确定了类似的最低三个数字的计算的看似琐碎的操作实际的瓶颈(即“临界3%”)在您的应用程序,那么你可能会考虑对其进行优化。

And in this case, this is actually possible: The Math#min(double,double) method in Java has very special semantics:在这种情况下,这实际上是可能的:Java 中的Math#min(double,double)方法具有非常特殊的语义:

Returns the smaller of two double values.返回两个双精度值中较小的一个。 That is, the result is the value closer to negative infinity.也就是说,结果是更接近负无穷大的值。 If the arguments have the same value, the result is that same value.如果参数具有相同的值,则结果是相同的值。 If either value is NaN, then the result is NaN.如果任一值为 NaN,则结果为 NaN。 Unlike the numerical comparison operators, this method considers negative zero to be strictly smaller than positive zero.与数值比较运算符不同,此方法认为负零严格小于正零。 If one argument is positive zero and the other is negative zero, the result is negative zero.如果一个参数为正零,另一个为负零,则结果为负零。

One can have a look at the implementation, and see that it's actually rather complex:可以看一下实现,会发现它实际上相当复杂:

public static double min(double a, double b) {
    if (a != a)
        return a;   // a is NaN
    if ((a == 0.0d) &&
        (b == 0.0d) &&
        (Double.doubleToRawLongBits(b) == negativeZeroDoubleBits)) {
        // Raw conversion ok since NaN can't map to -0.0.
        return b;
    }
    return (a <= b) ? a : b;
}

Now, it may be important to point out that this behavior is different from a simple comparison.现在,重要的是要指出这种行为不同于简单的比较。 This can easily be examined with the following example:这可以通过以下示例轻松检查:

public class MinExample
{
    public static void main(String[] args)
    {
        test(0.0, 1.0);
        test(1.0, 0.0);
        test(-0.0, 0.0);
        test(Double.NaN, 1.0);
        test(1.0, Double.NaN);
    }

    private static void test(double a, double b)
    {
        double minA = Math.min(a, b);
        double minB = a < b ? a : b;
        System.out.println("a: "+a);
        System.out.println("b: "+b);
        System.out.println("minA "+minA);
        System.out.println("minB "+minB);
        if (Double.doubleToRawLongBits(minA) !=
            Double.doubleToRawLongBits(minB))
        {
            System.out.println(" -> Different results!");
        }
        System.out.println();
    }
}

However: If the treatment of NaN and positive/negative zero is not relevant for your application, you can replace the solution that is based on Math.min with a solution that is based on a simple comparison, and see whether it makes a difference.但是:如果NaN和正/负零的处理与您的应用程序无关,您可以将基于Math.min的解决方案替换为基于简单比较的解决方案,看看是否有所不同。

This will, of course, be application dependent.当然,这将取决于应用程序。 Here is a simple, artificial microbenchmark ( to be taken with a grain of salt! )这是一个简单的人工微基准测试(请稍加保留

import java.util.Random;

public class MinPerformance
{
    public static void main(String[] args)
    {
        bench();
    }

    private static void bench()
    {
        int runs = 1000;
        for (int size=10000; size<=100000; size+=10000)
        {
            Random random = new Random(0);
            double data[] = new double[size];
            for (int i=0; i<size; i++)
            {
                data[i] = random.nextDouble();
            }
            benchA(data, runs);
            benchB(data, runs);
        }
    }

    private static void benchA(double data[], int runs)
    {
        long before = System.nanoTime();
        double sum = 0;
        for (int r=0; r<runs; r++)
        {
            for (int i=0; i<data.length-3; i++)
            {
                sum += minA(data[i], data[i+1], data[i+2]);
            }
        }
        long after = System.nanoTime();
        System.out.println("A: length "+data.length+", time "+(after-before)/1e6+", result "+sum);
    }

    private static void benchB(double data[], int runs)
    {
        long before = System.nanoTime();
        double sum = 0;
        for (int r=0; r<runs; r++)
        {
            for (int i=0; i<data.length-3; i++)
            {
                sum += minB(data[i], data[i+1], data[i+2]);
            }
        }
        long after = System.nanoTime();
        System.out.println("B: length "+data.length+", time "+(after-before)/1e6+", result "+sum);
    }

    private static double minA(double a, double b, double c)
    {
        return Math.min(a, Math.min(b, c));
    }

    private static double minB(double a, double b, double c)
    {
        if (a < b)
        {
            if (a < c)
            {
                return a;
            }
            return c;
        }
        if (b < c)
        {
            return b;
        }
        return c;
    }
}

(Disclaimer: Microbenchmarking in Java is an art, and for more reliable results, one should consider using JMH or Caliper ). (免责声明:Java 中的微基准测试是一门艺术,为了获得更可靠的结果,应该考虑使用JMHCaliper )。

Running this with JRE 1.8.0_31 may result in something like使用 JRE 1.8.0_31 运行它可能会导致类似

....
A: length 90000, time 545.929078, result 2.247805342620906E7
B: length 90000, time 441.999193, result 2.247805342620906E7
A: length 100000, time 608.046928, result 2.5032781001456387E7
B: length 100000, time 493.747898, result 2.5032781001456387E7

This at least suggests that it might be possible to squeeze out a few percent here (again, in a very artifical example).这至少表明有可能在这里挤出几个百分点(再次,在一个非常人为的例子中)。


Analyzing this further, by looking at the hotspot disassembly output created with进一步分析这一点,通过查看使用创建的热点反汇编输出

java -server -XX:+UnlockDiagnosticVMOptions -XX:+TraceClassLoading -XX:+LogCompilation -XX:+PrintAssembly MinPerformance

one can see the optimized versions of both methods, minA and minB .可以看到两种方法minAminB的优化版本。

First, the output for the method that uses Math.min :首先,使用Math.min的方法的输出:

Decoding compiled method 0x0000000002992310:
Code:
[Entry Point]
[Verified Entry Point]
[Constants]
  # {method} {0x000000001c010910} &apos;minA&apos; &apos;(DDD)D&apos; in &apos;MinPerformance&apos;
  # parm0:    xmm0:xmm0   = double
  # parm1:    xmm1:xmm1   = double
  # parm2:    xmm2:xmm2   = double
  #           [sp+0x60]  (sp of caller)
  0x0000000002992480: mov    %eax,-0x6000(%rsp)
  0x0000000002992487: push   %rbp
  0x0000000002992488: sub    $0x50,%rsp
  0x000000000299248c: movabs $0x1c010cd0,%rsi
  0x0000000002992496: mov    0x8(%rsi),%edi
  0x0000000002992499: add    $0x8,%edi
  0x000000000299249c: mov    %edi,0x8(%rsi)
  0x000000000299249f: movabs $0x1c010908,%rsi   ; {metadata({method} {0x000000001c010910} &apos;minA&apos; &apos;(DDD)D&apos; in &apos;MinPerformance&apos;)}
  0x00000000029924a9: and    $0x3ff8,%edi
  0x00000000029924af: cmp    $0x0,%edi
  0x00000000029924b2: je     0x00000000029924e8  ;*dload_0
                        ; - MinPerformance::minA@0 (line 58)

  0x00000000029924b8: vmovsd %xmm0,0x38(%rsp)
  0x00000000029924be: vmovapd %xmm1,%xmm0
  0x00000000029924c2: vmovapd %xmm2,%xmm1       ;*invokestatic min
                        ; - MinPerformance::minA@4 (line 58)

  0x00000000029924c6: nop
  0x00000000029924c7: callq  0x00000000028c6360  ; OopMap{off=76}
                        ;*invokestatic min
                        ; - MinPerformance::minA@4 (line 58)
                        ;   {static_call}
  0x00000000029924cc: vmovapd %xmm0,%xmm1       ;*invokestatic min
                        ; - MinPerformance::minA@4 (line 58)

  0x00000000029924d0: vmovsd 0x38(%rsp),%xmm0   ;*invokestatic min
                        ; - MinPerformance::minA@7 (line 58)

  0x00000000029924d6: nop
  0x00000000029924d7: callq  0x00000000028c6360  ; OopMap{off=92}
                        ;*invokestatic min
                        ; - MinPerformance::minA@7 (line 58)
                        ;   {static_call}
  0x00000000029924dc: add    $0x50,%rsp
  0x00000000029924e0: pop    %rbp
  0x00000000029924e1: test   %eax,-0x27623e7(%rip)        # 0x0000000000230100
                        ;   {poll_return}
  0x00000000029924e7: retq
  0x00000000029924e8: mov    %rsi,0x8(%rsp)
  0x00000000029924ed: movq   $0xffffffffffffffff,(%rsp)
  0x00000000029924f5: callq  0x000000000297e260  ; OopMap{off=122}
                        ;*synchronization entry
                        ; - MinPerformance::minA@-1 (line 58)
                        ;   {runtime_call}
  0x00000000029924fa: jmp    0x00000000029924b8
  0x00000000029924fc: nop
  0x00000000029924fd: nop
  0x00000000029924fe: mov    0x298(%r15),%rax
  0x0000000002992505: movabs $0x0,%r10
  0x000000000299250f: mov    %r10,0x298(%r15)
  0x0000000002992516: movabs $0x0,%r10
  0x0000000002992520: mov    %r10,0x2a0(%r15)
  0x0000000002992527: add    $0x50,%rsp
  0x000000000299252b: pop    %rbp
  0x000000000299252c: jmpq   0x00000000028ec620  ; {runtime_call}
  0x0000000002992531: hlt
  0x0000000002992532: hlt
  0x0000000002992533: hlt
  0x0000000002992534: hlt
  0x0000000002992535: hlt
  0x0000000002992536: hlt
  0x0000000002992537: hlt
  0x0000000002992538: hlt
  0x0000000002992539: hlt
  0x000000000299253a: hlt
  0x000000000299253b: hlt
  0x000000000299253c: hlt
  0x000000000299253d: hlt
  0x000000000299253e: hlt
  0x000000000299253f: hlt
[Stub Code]
  0x0000000002992540: nop                       ;   {no_reloc}
  0x0000000002992541: nop
  0x0000000002992542: nop
  0x0000000002992543: nop
  0x0000000002992544: nop
  0x0000000002992545: movabs $0x0,%rbx          ; {static_stub}
  0x000000000299254f: jmpq   0x000000000299254f  ; {runtime_call}
  0x0000000002992554: nop
  0x0000000002992555: movabs $0x0,%rbx          ; {static_stub}
  0x000000000299255f: jmpq   0x000000000299255f  ; {runtime_call}
[Exception Handler]
  0x0000000002992564: callq  0x000000000297b9e0  ; {runtime_call}
  0x0000000002992569: mov    %rsp,-0x28(%rsp)
  0x000000000299256e: sub    $0x80,%rsp
  0x0000000002992575: mov    %rax,0x78(%rsp)
  0x000000000299257a: mov    %rcx,0x70(%rsp)
  0x000000000299257f: mov    %rdx,0x68(%rsp)
  0x0000000002992584: mov    %rbx,0x60(%rsp)
  0x0000000002992589: mov    %rbp,0x50(%rsp)
  0x000000000299258e: mov    %rsi,0x48(%rsp)
  0x0000000002992593: mov    %rdi,0x40(%rsp)
  0x0000000002992598: mov    %r8,0x38(%rsp)
  0x000000000299259d: mov    %r9,0x30(%rsp)
  0x00000000029925a2: mov    %r10,0x28(%rsp)
  0x00000000029925a7: mov    %r11,0x20(%rsp)
  0x00000000029925ac: mov    %r12,0x18(%rsp)
  0x00000000029925b1: mov    %r13,0x10(%rsp)
  0x00000000029925b6: mov    %r14,0x8(%rsp)
  0x00000000029925bb: mov    %r15,(%rsp)
  0x00000000029925bf: movabs $0x515db148,%rcx   ; {external_word}
  0x00000000029925c9: movabs $0x2992569,%rdx    ; {internal_word}
  0x00000000029925d3: mov    %rsp,%r8
  0x00000000029925d6: and    $0xfffffffffffffff0,%rsp
  0x00000000029925da: callq  0x00000000512a9020  ; {runtime_call}
  0x00000000029925df: hlt
[Deopt Handler Code]
  0x00000000029925e0: movabs $0x29925e0,%r10    ; {section_word}
  0x00000000029925ea: push   %r10
  0x00000000029925ec: jmpq   0x00000000028c7340  ; {runtime_call}
  0x00000000029925f1: hlt
  0x00000000029925f2: hlt
  0x00000000029925f3: hlt
  0x00000000029925f4: hlt
  0x00000000029925f5: hlt
  0x00000000029925f6: hlt
  0x00000000029925f7: hlt

One can see that the treatment of special cases involves some effort - compared to the output that uses simple comparisons, which is rather straightforward:可以看到,处理特殊情况需要付出一些努力——与使用简单比较的输出相比,这是相当直接的:

Decoding compiled method 0x0000000002998790:
Code:
[Entry Point]
[Verified Entry Point]
[Constants]
  # {method} {0x000000001c0109c0} &apos;minB&apos; &apos;(DDD)D&apos; in &apos;MinPerformance&apos;
  # parm0:    xmm0:xmm0   = double
  # parm1:    xmm1:xmm1   = double
  # parm2:    xmm2:xmm2   = double
  #           [sp+0x20]  (sp of caller)
  0x00000000029988c0: sub    $0x18,%rsp
  0x00000000029988c7: mov    %rbp,0x10(%rsp) ;*synchronization entry
                        ; - MinPerformance::minB@-1 (line 63)

  0x00000000029988cc: vucomisd %xmm0,%xmm1
  0x00000000029988d0: ja     0x00000000029988ee  ;*ifge
                        ; - MinPerformance::minB@3 (line 63)

  0x00000000029988d2: vucomisd %xmm1,%xmm2
  0x00000000029988d6: ja     0x00000000029988de  ;*ifge
                        ; - MinPerformance::minB@22 (line 71)

  0x00000000029988d8: vmovapd %xmm2,%xmm0
  0x00000000029988dc: jmp    0x00000000029988e2
  0x00000000029988de: vmovapd %xmm1,%xmm0 ;*synchronization entry
                        ; - MinPerformance::minB@-1 (line 63)

  0x00000000029988e2: add    $0x10,%rsp
  0x00000000029988e6: pop    %rbp
  0x00000000029988e7: test   %eax,-0x27688ed(%rip)        # 0x0000000000230000
                        ;   {poll_return}
  0x00000000029988ed: retq
  0x00000000029988ee: vucomisd %xmm0,%xmm2
  0x00000000029988f2: ja     0x00000000029988e2  ;*ifge
                        ; - MinPerformance::minB@10 (line 65)

  0x00000000029988f4: vmovapd %xmm2,%xmm0
  0x00000000029988f8: jmp    0x00000000029988e2
  0x00000000029988fa: hlt
  0x00000000029988fb: hlt
  0x00000000029988fc: hlt
  0x00000000029988fd: hlt
  0x00000000029988fe: hlt
  0x00000000029988ff: hlt
[Exception Handler]
[Stub Code]
  0x0000000002998900: jmpq   0x00000000028ec920  ;   {no_reloc}
[Deopt Handler Code]
  0x0000000002998905: callq  0x000000000299890a
  0x000000000299890a: subq   $0x5,(%rsp)
  0x000000000299890f: jmpq   0x00000000028c7340  ; {runtime_call}
  0x0000000002998914: hlt
  0x0000000002998915: hlt
  0x0000000002998916: hlt
  0x0000000002998917: hlt

Whether or not there are cases where such an optimization really makes a difference in an application is hard to tell.很难说这种优化是否真的对应用程序产生了影响。 But at least, the bottom line is:但至少,底线是:

  • The Math#min(double,double) method is not the same as a simple comparison, and the treatment of the special cases does not come for free Math#min(double,double)方法不是简单的比较,特殊情况的处理不是免费来的
  • There are cases where the special case treatment that is done by Math#min is not necessary, and then a comparison-based approach may be more efficient在某些情况下, Math#min所做的特殊情况处理不是必需的,然后基于比较的方法可能会更有效
  • As already pointed out in other answers: In most cases, the performance difference will not matter.正如其他答案中已经指出的那样:在大多数情况下,性能差异无关紧要。 However, for this particular example, one should probably create a utility method min(double,double,double) anyhow, for better convenience and readability, and then it would be easy to do two runs with the different implementations, and see whether it really affects the performance.然而,对于这个特定的例子,无论如何,为了更好的方便性和可读性,我们应该创建一个实用方法min(double,double,double) ,然后很容易用不同的实现进行两次运行,看看它是否真的影响性能。

(Side note: The integer type methods, like Math.min(int,int) actually are a simple comparison - so I would expect no difference for these). (旁注:整数类型方法,如Math.min(int,int)实际上一个简单的比较 - 所以我希望这些方法没有区别)。

You can use ternary operator as follows:您可以按如下方式使用三元运算符:

smallest=(a<b)?((a<c)?a:c):((b<c)?b:c);

Which takes only one assignment and minimum two comparisons.只需要一次分配和最少两次比较。

But I think that these statements would not have any effect on execution time, your initial logic will take same time as of mine and all of others.但是我认为这些语句不会对执行时间产生任何影响,您的初始逻辑将花费与我和所有其他人相同的时间。

OP's efficient code has a bug: OP的高效代码有一个bug:

when a == b , and a (or b) < c , the code will pick c instead of a or b.a == ba (or b) < c ,代码将选择 c 而不是 a 或 b。

For those who find this topic much later:对于那些后来发现这个话题的人:

If you have just three values to compare there is no significant difference.如果您只有三个要比较的值,则没有显着差异。 But if you have to find min of, say, thirty or sixty values, "min" could be easier for anyone to read in the code next year:但是,如果您必须找到 min,例如,三十或六十个值,那么明年任何人都可以更轻松地阅读“min”:

int smallest;

smallest = min(a1, a2);
smallest = min(smallest, a3);
smallest = min(smallest, a4);
...
smallest = min(smallest, a37);

But if you think of speed, maybe better way would be to put values into list, and then find min of that:但是,如果您考虑速度,也许更好的方法是将值放入列表中,然后找到其中的最小值:

List<Integer> mySet = Arrays.asList(a1, a2, a3, ..., a37);

int smallest = Collections.min(mySet);

Would you agree?你会同意吗?

Math.min uses a simple comparison to do its thing. Math.min使用一个简单的比较来完成它的工作。 The only advantage to not using Math.min is to save the extra function calls, but that is a negligible saving.不使用 Math.min 的唯一优势是节省了额外的函数调用,但这是一个可以忽略不计的节省。

If you have more than just three numbers, having a minimum method for any number of double s might be valuable and would look something like:如果您的数字不止三个,则为任意数量的double设置一个minimum方法可能很有价值,看起来像:

public static double min(double ... numbers) {
    double min = numbers[0];
    for (int i=1 ; i<numbers.length ; i++) {
        min = (min <= numbers[i]) ? min : numbers[i];
    }
    return min;
}

For three numbers this is the functional equivalent of Math.min(a, Math.min(b, c));对于三个数字,这是Math.min(a, Math.min(b, c));等价函数Math.min(a, Math.min(b, c)); but you save one method invocation.但是您保存了一个方法调用。

double smallest;
if(a<b && a<c){
    smallest = a;
}else if(b<c && b<a){
    smallest = b;
}else{
    smallest = c;
}

can be improved to:可以改进为:

double smallest;
if(a<b && a<c){
smallest = a;
}else if(b<c){
    smallest = b;
}else{
    smallest = c;
}

对于纯字符代码效率,我找不到比

smallest = a<b&&a<c?a:b<c?b:c;

Use the Arrays.sort() method, the lowest value will be element0.使用 Arrays.sort() 方法,最低值为 element0。

In terms of performance, this should not be expensive since the sort operation is already optimised.在性能方面,这不应该是昂贵的,因为排序操作已经优化。 Also has the advantage of being concise.还具有简洁的优点。

private int min(int ... value) {
    Arrays.sort(value);
    return value[0];
}

Proof of concept概念证明

    int[] intArr = {12, 5, 6, 9, 44, 28, 1, 4, 18, 2, 66, 13, 1, 33, 74, 12, 
    5, 6, 9, 44, 28, 1, 4, 18, 2, 66, 13};

    // Sorting approach
    long startTime = System.currentTimeMillis();
    int minVal = min(intArr);
    long endTime = System.currentTimeMillis();
    System.out.println("Sorting: Min => " + minVal + " took => " + (endTime - 
    startTime));
    System.out.println(startTime + "   "  + endTime);
    System.out.println(" ");

    // Scanning approach
    minVal = 100;
    startTime = System.currentTimeMillis();
    for(int val : intArr) {
        if (val < minVal)
            minVal = val;
    }
    endTime = System.currentTimeMillis();
    System.out.println("Iterating: Min => " + minVal + " took => " + (endTime 
    - startTime));
    System.out.println(startTime + "   "  + endTime);

在此处输入图片说明

If you will call min() around 1kk times with different a, b, c, then use my method:如果您将使用不同的 a、b、c 调用 min() 大约 1kk 次,请使用我的方法:

Here only two comparisons.这里只做两个比较。 There is no way to calc faster :P没有办法计算得更快:P

public static double min(double a, double b, double c) {
    if (a > b) {     //if true, min = b
        if (b > c) { //if true, min = c
            return c;
        } else {     //else min = b
            return b; 
        }
    }          //else min = a
    if (a > c) {  // if true, min=c
        return c;
    } else {
        return a;
    }
}

It all looks ok, your code will be fine, unless you're doing this in a tight loop.一切看起来都不错,你的代码会很好,除非你在一个紧密的循环中这样做。 I also would consider我也会考虑

double min;
min = (a<b) ? a : b;
min = (min<c) ? min : c;

Works with an arbitrary number of input values:适用于任意数量的输入值:

 public static double min(double... doubles) {
    double m = Double.MAX_VALUE;
    for (double d : doubles) {
        m = Math.min(m, d);
    }
    return m;
}

I would use min/max (and not worry otherwise) ... however, here is another "long hand" approach which may or may not be easier for some people to understand.我会使用min/max (否则不用担心)......但是,这是另一种“长手”方法,对于某些人来说可能更容易理解,也可能不会更容易理解。 (I would not expect it to be faster or slower than the code in the post.) (我希望它比帖子中的代码更快或更慢。)

int smallest;
if (a < b) {
  if (a > c) {
    smallest = c;
  } else { // a <= c
    smallest = a;
  }
} else { // a >= b
  if (b > c) {
    smallest = c;
  } else { // b <= c
    smallest = b;
  }
}

Just throwing it into the mix.只是把它扔进去。

Note that this is just the side-effecting variant of Abhishek's answer.请注意,这只是 Abhishek 答案的副作用变体。

Write a method minimum3 that returns the smallest of three floating-point numbers.编写一个返回三个浮点数中最小的一个的方法 minimum3。 Use the Math.min method to implement minimum3.使用 Math.min 方法实现 minimum3。 Incorporate the method into an application that reads three values from the user, determines the smallest value and displays the result.将该方法合并到一个应用程序中,该应用程序从用户那里读取三个值,确定最小值并显示结果。

Simply use this math function只需使用这个数学函数

System.out.println(Math.min(a,b,c));

You will get the answer in single line.您将在单行中得到答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM