【问题标题】:Most efficient way to find smallest of 3 numbers Java?找到Java中最小的3个数字的最有效方法?
【发布时间】:2012-03-06 01:19:02
【问题描述】:

我有一个用 Java 编写的算法,我想提高它的效率。我认为可以提高效率的部分是找到 3 个数字中最小的一个。目前我正在使用Math.min方法如下:

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

这效率如何?用下面的 if 语句替换会更有效吗:

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

或者如果有其他更有效的方法

我想知道是否值得改变我目前使用的东西?

任何速度的提高都会有很大帮助

【问题讨论】:

  • 期望从基本的数字比较中获得任何有意义的性能影响是在兔子洞里跳得太远了。
  • 是的,这是毫无意义的优化。这种操作的成本是无限小的。话虽如此,我可能会坚持使用您的 Math.min 构造。
  • Math.pow 使用 for 循环。所以说你做了 math.pow(4,3),你会说 {double result = 4;for (int i = 0; i
  • HotSpot 将内联您对 Math.min() 的调用,如果它们足够热的话,但为了完整起见,应该提到在您建议的代码中
  • Google for premature optimization,然后分析您的代码。

标签: java performance algorithm min


【解决方案1】:

对于许多实用程序类型的方法,apache 公共库具有可靠的实现,您可以利用这些实现或从中获得更多见解。在这种情况下,有一种方法可以在 org.apache.commons.lang.math.NumberUtils 中找到三个可用的双精度中最小的一个。它们的实现实际上与您最初的想法几乎相同:

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

【讨论】:

    【解决方案2】:

    不,它真的值得改变。在摆弄像这样的微优化时,您将获得的那种改进是不值得的。如果min函数被调用足够多,即使是方法调用成本也会被移除。

    如果您的算法有问题,最好的办法是研究宏观优化(“全局”的东西,如算法选择或调整) - 您通常会获得很多更好的性能那里的改进。

    您关于删除Math.pow 进行改进的评论可能是正确的,但那是因为它是一项相对昂贵的操作。 Math.min 在成本方面甚至不会接近。

    【讨论】:

    • 感谢非常有帮助。我正在尝试不同的优化,但我还需要收集这个基本案例的结果以便能够进行比较:(
    • 当你必须调用一个三路分钟数十万次时,它加起来
    • @Michael,问题中似乎没有任何迹象表明您会这样做数十万次。如果你是,我不会使用min 一次处理三个数字 - 我会遍历数十万个数字的列表一次获得最小值。而且,正如我所说,如果您确实经常调用它,JIT 编译器几乎肯定会编译/内联它。考虑到所有其他答案,这似乎也是共识观点。
    【解决方案3】:
    double smallest = a;
    if (smallest > b) smallest = b;
    if (smallest > c) smallest = c;
    

    不一定比您的代码快。

    【讨论】:

      【解决方案4】:

      让我首先通过引用 Donald Knuth 的文章“使用 go to 语句进行结构化编程”来重复其他人已经说过的话:

      我们应该忘记小的效率,比如大约 97% 的时间:过早优化是万恶之源。

      然而,我们不应该放弃那关键的 3% 的机会。一个好的程序员不会因为这样的推理而自满,他会明智地仔细查看关键代码;但只有在识别出该代码之后。

      (我强调)

      因此,如果您发现像计算三个数字的最小值这样看似微不足道的操作应用程序中的实际瓶颈(即“关键 3%”),那么您可以考虑优化一下。

      而在这种情况下,这实际上是可能的:Java 中的Math#min(double,double) 方法具有非常特殊的语义:

      返回两个双精度值中较小的一个。也就是说,结果是更接近负无穷大的值。如果参数具有相同的值,则结果是相同的值。如果任一值为 NaN,则结果为 NaN。与数值比较运算符不同,此方法认为负零严格小于正零。如果一个参数为正零而另一个为负零,则结果为负零。

      可以看一下实现,发现它实际上相当复杂:

      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;
      }
      

      现在,指出这种行为与简单比较不同可能很重要。这可以通过以下示例轻松检查:

      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();
          }
      }
      

      但是:如果NaN 和正/负零的处理与您的应用程序无关,您可以将基于Math.min 的解决方案替换为基于简单比较的解决方案,并查看是否它有所作为。

      当然,这将取决于应用程序。这是一个简单的人工微基准测试(持保留态度!

      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;
          }
      }
      

      (免责声明:Java 中的微基准测试是一门艺术,为了获得更可靠的结果,应该考虑使用JMHCaliper)。

      使用 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
      

      这至少表明可能会在这里挤出几个百分点(再次,在一个非常人为的例子中)。


      通过查看创建的热点反汇编输出来进一步分析

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

      可以看到minAminB这两种方法的优化版本。

      首先,使用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
      

      可以看出,处理特殊情况需要付出一些努力——与使用简单比较的输出相比,这相当简单:

      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
      

      很难说这种优化是否真的会对应用程序产生影响。但至少,底线是:

      • Math#min(double,double)方法和简单的比较一样,特殊情况的处理也不是免费的
      • 在某些情况下,Math#min 所做的特殊情况处理不是必需的,然后基于比较的方法可能更有效
      • 正如其他答案中已经指出的那样:在大多数情况下,性能差异并不重要。然而,对于这个特定的例子,一个人可能应该创建一个实用方法min(double,double,double),为了更好的方便和可读性,然后很容易用不同的实现进行两次运行,看看它是否真的影响性能。

      (旁注:整数类型的方法,例如Math.min(int,int) 实际上一个简单的比较 - 所以我希望这些没有差异)。

      【讨论】:

        【解决方案5】:

        您可以使用如下三元运算符:

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

        只需要一次分配和最少两次比较。

        但我认为这些语句不会对执行时间产生任何影响,您的初始逻辑将花费与我和其他所有人相同的时间。

        【讨论】:

        • 请注意,这将返回最大的数字,而不是最小的。
        • @Sietse 这不会返回。它将abc 中最小的一个分配给smallest
        【解决方案6】:

        OP的高效代码有个bug:

        a == ba (or b) &lt; c 时,代码将选择c 而不是a 或b。

        【讨论】:

        • 虽然这是一个很好的发现,之前没有人(明确地)提到过,但这并不能回答这个问题:投票只是为了让您有特权尽快将其变成评论。考虑editing the question
        • (问题中的代码已于 2018 年 8 月 13 日 18:33 更正)
        【解决方案7】:

        对于那些后来发现这个主题的人:

        如果您只有三个值要比较,则没有显着差异。但是如果你必须找到最小值,比如 30 或 60 个值,那么明年任何人都可以更容易地在代码中阅读“min”:

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

        但是如果您考虑速度,也许更好的方法是将值放入列表中,然后找到其中的最小值:

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

        你同意吗?

        【讨论】:

        • 不是我,一个。虽然我很难想象拥有 37 个值并“需要”最小值,但我看不出Collections.min() 将如何帮助speed。 Java 在“隐式并行/并发”方面的尝试是 stream
        • 谢谢。例如,对于 37 个值,当您决定为 Y 值组绘制的图形范围时可能需要它。您需要 min 和 max 来确定图形的 Y 跨度。
        【解决方案8】:

        Math.min 使用简单的比较来完成它的工作。不使用 Math.min 的唯一好处是节省了额外的函数调用,但节省的时间可以忽略不计。

        如果您有不止三个数字,则为任意数量的doubles 使用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;
        }
        

        对于三个数字,这与Math.min(a, Math.min(b, c)); 的功能等效,但您保存了一个方法调用。

        【讨论】:

        • 对此的(后期)评论:Math.min 仅对整数数据类型进行简单比较。但对于doublefloat,它还处理了NaN 等特殊情况。
        【解决方案9】:
        double smallest;
        if(a<b && a<c){
            smallest = a;
        }else if(b<c && b<a){
            smallest = b;
        }else{
            smallest = c;
        }
        

        可以改进为:

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

        【讨论】:

        • 在我看来,这是唯一真正的答案之一。这是对 OP 代码的一个非常小的改动,从而提高了它的效率。解释这个问题如何是微优化并不是一个答案。有些人的热点可能正好在这样的函数中。
        【解决方案10】:

        看起来一切正常,您的代码会很好,除非您在一个紧密的循环中执行此操作。我也会考虑

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

        【讨论】:

          【解决方案11】:

          如果你会用不同的 a、b、c 调用 min() 大约 1kk 次,那么使用我的方法:

          这里只有两个比较。没有办法更快地计算: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;
              }
          }
          

          【讨论】:

            【解决方案12】:

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

            更好的东西了
            smallest = a<b&&a<c?a:b<c?b:c;
            

            【讨论】:

            • 你可能想去打高尔夫球。
            【解决方案13】:

            使用 Arrays.sort() 方法,最小值为 element0。

            就性能而言,这应该不会很昂贵,因为排序操作是 已经优化。也有简洁的优点。

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

            概念证明

                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);
            

            【讨论】:

            • 一般来说排序是O(N log N),而扫描数据只有O(N)
            • @tgdavies 感谢您的评论。我在这两种方法之间进行了验证测试,使用 15 个值,它们在大约 15 毫秒内完成。
            • @james 对于大小大于 15 的数组,您会发现此解决方案的效率低于检查每个元素一次 O(n)。请看stackoverflow.com/questions/4973045/…
            【解决方案14】:

            我会使用min/max(否则不用担心)......但是,这是另一种“长手”方法,对于某些人来说可能更容易理解,也可能不容易理解。 (我期望它比帖子中的代码更快或更慢。)

            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;
              }
            }
            

            只是把它扔进去。

            请注意,这只是 Abhishek 答案的副作用。

            【讨论】:

              【解决方案15】:

              适用于任意数量的输入值:

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

              【讨论】:

                【解决方案16】:

                只需使用这个数学函数

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

                您将在一行中得到答案。

                【讨论】:

                • 问题是关于效率的。因此,在回答中,您应该提供一些解释为什么您的代码更有效。短码和快码不一样。
                • 这个答案是废话。 Java 中没有 3 参数 Math.min 函数。阅读 javadocs。
                猜你喜欢
                • 1970-01-01
                • 2011-01-03
                • 2011-01-15
                • 1970-01-01
                • 2013-11-10
                • 1970-01-01
                • 1970-01-01
                • 2022-10-14
                • 2014-08-01
                相关资源
                最近更新 更多