【问题标题】:Most efficient way to find the greatest of three ints找到三个整数中最大值的最有效方法
【发布时间】:2011-01-15 01:05:54
【问题描述】:

下面是我的伪代码。

function highest(i, j, k)
{
  if(i > j && i > k)
  {
    return i;
  }
  else if (j > k)
  {
    return j;
  }
  else
  {
    return k;
  }
}

我认为这可行,但这是 C++ 中最有效的方式吗?

【问题讨论】:

  • 在这种情况下,如果是作业,没关系,因为提问者已经尝试过,显示了他的代码并要求改进。这符合在 SO 上发布家庭作业问题的所有准则。
  • @Robert Greiner 哈哈,不。虽然这会是一个很好的家庭作业问题,不是吗?
  • @Stephano:您对其进行分析并确定它是否是您程序中的主要减速因素。担心一切的效率是一个常见的错误;让代码易于理解和编写,让编译器完成它的一部分。
  • 这是最有效的方法:/* Precondition: i is the largest value of the three. */ int max(int i, int j, int k) { return i; } 或者可能只返回 42。

标签: c++ performance max min


【解决方案1】:

要找到最大的整数,您需要查看 3 个整数,不多不少。您正在查看 6 和 3 比较。您应该能够在 3 和 2 比较中做到这一点。

int ret = max(i,j);
ret = max(ret, k);
return ret;

【讨论】:

  • 可以做一个不错的小功能:template <typename T> const T& max(const T& pA, const T& pB, const T& pC){ return max(pA, max(pB, pC)); }
  • max(i, max(j, k)) 将其保存到一行。我也喜欢模板版
  • 当然,如果 max 是宏或内联函数,max(i, max(j, k)) 将扩展为类似于 i > ( j > k ? j : k ) ? i : ( j > k ? j : k ) 的内容(尽管有 CSE 优化),如果不是,你有函数调用开销。我们是在谈论程序员效率还是计算效率?
  • @Duncan:当它是一个内联函数时,你错了,因为这个问题是 C++,所以我们谈论的是 std::max。一个名为“max”的宏在 C++ 中是纯粹的可憎之物。
  • @Roger Pate:即使在 C 语言中,宏也是令人厌恶的 :)。也许我应该说“..一个模板或内联......” 那么内联表达式会发生什么?当然,这将内联到 rv1 = j > k ? j : k; rv2 = i > rv1 ? i : rv1; return rv2; 之类的东西,这与 CSE 相同。我错过了什么吗?自从我上次费心研究生成的汇编语言以来,也许在这 2 年里事情已经发生了变化。我不介意被告知我错了,尽管我更愿意被告知原因:)
【解决方案2】:

伪代码:

result = i
if j > result:
  result = j
if k > result:
  result = k
return result

【讨论】:

  • 我喜欢你只使用 if 语句。这是一个干净的答案。
  • 太棒了!非常清楚,并且很可能如果硬件具有像cmov 这样的谓词指令,编译器将使用它们。 +1(希望我能超越邪恶 +10 max
  • 很好的答案。尽可能简单,无需尝试变得聪明。 +1 表示谦虚。
【解决方案3】:

怎么样

return i > j? (i > k? i: k): (j > k? j: k);

两次比较,暂不使用临时栈变量...

【讨论】:

  • +1。漂亮。既迷人又伤眼。
  • +1 是第一个提到单行解决方案的人。我可能不愿意尝试缩短所有内容的想法,但时不时有人向我展示令人印象深刻的 1-liner。
【解决方案4】:

您当前的方法: http://ideone.com/JZEqZTlj (0.40s)

克里斯的解决方案:

int ret = max(i,j);
ret = max(ret, k);
return ret;

http://ideone.com/hlnl7QZX (0.39s)

Ignacio Vazquez-Abrams 的解决方案:

result = i;
if (j > result)
  result = j;
if (k > result)
  result = k;
return result;

http://ideone.com/JKbtkgXi (0.40s)

还有查尔斯·布雷塔纳的:

return i > j? (i > k? i: k): (j > k? j: k);

http://ideone.com/kyl0SpUZ (0.40s)

在这些测试中,所有解决方案的执行时间都比其他解决方案少 3%。您尝试优化的代码非常短。即使您能够从中挤出 1 条指令,也不太可能在整个程序中产生巨大的差异(现代编译器可能会捕捉到那个小的优化)。把时间花在别处。

编辑: 更新了测试,结果发现它之前仍在优化其中的一部分。希望不再是这样了。

【讨论】:

  • 好的,我(稍微)对更新的版本感到满意。 SO不会让我删除-1(“投票太旧而无法更改,除非编辑此答案”),对不起。
  • 哇,亲爱的。我不知道ideone存在。当我无法入睡时,这让我有事可做:)。
【解决方案5】:

对于这样的问题,只有知道优化编译器在做什么以及硬件上可用的内容是什么,这是无可替代的。如果您拥有的基本工具是二进制比较或二进制最大值,那么两次比较或最大值都是必要且充分的。

我更喜欢 Ignacio 的解决方案:

result = i;
if (j > result)
  result = j;
if (k > result)
  result = k;
return result;

因为在常见的现代 Intel 硬件上,编译器会发现只发出两个比较和两个 cmov 指令非常容易,与条件分支相比,它们对 I-cache 的负载更小,对分支预测器的压力也更小. (此外,代码清晰易读。)如果您使用的是 x86-64,编译器甚至会将所有内容保存在寄存器中。

请注意,您将很难将此代码嵌入到您的选择产生影响的程序中...

【讨论】:

    【解决方案6】:

    我喜欢将条件跳跃作为一种智力练习来消除。这是否对性能有任何可衡量的影响我不知道:)

    #include <iostream>
    #include <limits>
    
    inline int max(int a, int b)
    {
        int difference = a - b;
        int b_greater = difference >> std::numeric_limits<int>::digits;
        return a - (difference & b_greater);
    }
    
    int max(int a, int b, int c)
    {
        return max(max(a, b), c);
    }
    
    int main()
    {
        std::cout << max(1, 2, 3) << std::endl;
        std::cout << max(1, 3, 2) << std::endl;
        std::cout << max(2, 1, 3) << std::endl;
        std::cout << max(2, 3, 1) << std::endl;
        std::cout << max(3, 1, 2) << std::endl;
        std::cout << max(3, 2, 1) << std::endl;
    }
    

    这点小玩意儿,cmov 解决方案可能快很多。

    【讨论】:

    • 移位加二元与运算很聪明!
    【解决方案7】:

    不确定这是否是最有效的,但可能是,而且肯定更短:

    int maximum = max( max(i, j), k);
    

    【讨论】:

      【解决方案8】:

      有一个提议将其包含在 N2485 下的 C++ 库中。这个提议很简单,所以我在下面包含了有意义的代码。显然,这假设了可变参数模板

      template < typename T >
      const T & max ( const T & a )
      { return a ; }
      
      template < typename T , typename ... Args >
      const T & max( const T & a , const T & b , const Args &... args )
      { return  max ( b > a ? b : a , args ...); }
      

      【讨论】:

        【解决方案9】:
        public int maximum(int a,int b,int c){
            int max = a;
            if(b>max)
                max = b;
            if(c>max)
                max = c;
            return max;
        }
        

        【讨论】:

          【解决方案10】:

          我认为“最有效”是指性能,尽量不浪费计算资源。但是您可能指的是编写更少的代码行,或者可能是关于源代码的可读性。我在下面提供了一个示例,您可以评估是否发现有用的东西,或者您是否更喜欢收到的答案中的其他版本。

          /* Java version, whose syntax is very similar to C++. Call this program "LargestOfThreeNumbers.java" */
          class LargestOfThreeNumbers{
              public static void main(String args[]){
                  int x, y, z, largest;
                  x = 1;
                  y = 2;
                  z = 3;
                  largest = x;
                  if(y > x){
                      largest = y;
                      if(z > y){
                          largest = z;
                      }
                  }else if(z > x){
                      largest = z;
                  }
                  System.out.println("The largest number is: " + largest);
              }
          }
          

          【讨论】:

            【解决方案11】:
            #include<stdio.h>
            int main()
            {
                int a,b,c,d,e;
                scanf("%d %d %d",&a,&b,&c);
                d=(a+b+abs(a-b))/2;
                e=(d+c+abs(c-d))/2;
                printf("%d is Max\n",e);
                return 0;
            }
            

            【讨论】:

              【解决方案12】:

              在 c++ 中查找最大或最小 2 个或更多数字的最简单方法是:-

              int a = 3, b = 4, c = 5;
              int maximum = max({a, b, c});
              
              int a = 3, b = 4, c = 5;
              int minimum = min({a, b, c});
              

              您可以提供任意数量的变量。

              有趣的是,它也非常高效,至少与 Ignacio Vazquez-Abrams 的解决方案 (https://godbolt.org/z/j1KM97) 一样高效:

                      mov     eax, dword ptr [rsp + 8]
                      mov     ecx, dword ptr [rsp + 4]
                      cmp     eax, ecx
                      cmovl   eax, ecx
                      mov     ecx, dword ptr [rsp]
                      cmp     eax, ecx
                      cmovl   eax, ecx
              

              与 GCC 类似,而 MSVC 会造成循环混乱。

              【讨论】:

                【解决方案13】:

                在 C# 中查找 3 位之间的最大和最小数字

                static void recorrectFindSmallestNumber()
                {
                int x = 30, y = 22, z = 11;
                if (x < y)
                {
                if (x < z)
                {
                Console.WriteLine("X is Smaller Numebr {0}.", x);
                }
                else
                {
                Console.WriteLine("z is Smaller Numebr {0}.", z);
                }
                }
                else if (x > y)
                {
                if (y < z)
                {
                Console.WriteLine("y is Smaller number.{0}", y);
                }
                else
                {
                Console.WriteLine("z is Smaller number.{0}", z);
                }
                }
                 else
                {
                
                }
                }
                

                ================================================ ==================

                static void recorrectFindLargeNumber()
                {
                int x, y, z;
                Console.WriteLine("Enter the first number:");
                x = int.Parse(Console.ReadLine());
                Console.WriteLine("Enter the second number:");
                y = int.Parse(Console.ReadLine());
                Console.WriteLine("Enter the third nuumnber:");
                z = int.Parse(Console.ReadLine());
                if (x > y)
                {
                if (x > z)
                {
                Console.WriteLine("X is Greater numbaer: {0}.", x);
                }
                else
                {
                Console.WriteLine("Z is greatest number: {0}.", z);
                }
                }
                else if (x < y)
                {
                if (y > z)
                {
                Console.WriteLine("y is Greater Number: {0}", y);
                }
                else 
                {
                Console.WriteLine("Z is Greater Number; {0}", z);                
                }
                }
                else
                {
                                
                }
                }
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2021-11-26
                  • 1970-01-01
                  • 2014-08-01
                  • 2015-05-22
                  • 1970-01-01
                  • 1970-01-01
                  • 2022-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多