Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 解释这个不使用if-else或任何其他比较运算符查找两个整数的最大值的代码段?_C_Algorithm_Math_Bit Manipulation_Max - Fatal编程技术网

C 解释这个不使用if-else或任何其他比较运算符查找两个整数的最大值的代码段?

C 解释这个不使用if-else或任何其他比较运算符查找两个整数的最大值的代码段?,c,algorithm,math,bit-manipulation,max,C,Algorithm,Math,Bit Manipulation,Max,找到两个数字中的最大值。不应使用if-else或任何其他比较运算符。我在网上的布告栏上发现了这个问题,所以我想我应该在网上提问 范例 输入:5,10 产出:10 我找到了这个解决方案,有人能帮我理解这些代码行吗 int getMax(int a, int b) { int c = a - b; int k = (c >> 31) & 0x1; int max = a - k * c; return max; } 我们开始:

找到两个数字中的最大值。不应使用if-else或任何其他比较运算符。我在网上的布告栏上发现了这个问题,所以我想我应该在网上提问

范例 输入:5,10 产出:10

我找到了这个解决方案,有人能帮我理解这些代码行吗

int getMax(int a, int b) {  
    int c = a - b;  
    int k = (c >> 31) & 0x1;  
    int max = a - k * c;  
    return max;  
}
我们开始:
(a+b)/2+|a-b |/2

使用按位黑客

r = x ^ ((x ^ y) & -(x < y)); // max(x, y)
资料来源:

让我们仔细分析一下。这第一行看起来很简单——它存储了
a
b
之间的差异。如果
a
此值为负值,否则为非负值。但实际上这里有一个bug-如果数字
a
b
的差异太大,无法放入整数,这将导致未定义的行为-哎呀!让我们假设这不会发生在这里

下一行是

int k = (c >> 31) & 0x1;
其目的是检查
c
的值是否为负值。在几乎所有现代计算机中,数字都是以一种称为2的补码的格式存储的,如果数字为正,则数字的最高位为0,如果数字为负,则数字的最高位为1。此外,大多数整数是32位的<代码>(c>>31)
将数字向下移动31位,将数字的最高位保留在最低位的位置。下一步,取这个数字,并将其与1(除最后一位外,其二进制表示形式在任何地方都是0)进行ANDing,将删除所有较高的位,只给出最低的位。由于
c>>31
的最低位是
c
的最高位,因此将
c
的最高位读取为0或1。由于当
c
为1时,最高位为1,因此这是一种检查
c
是负(1)还是正(0)的方法。结合上述推理,
k
如果
a
则为1,否则为0

最后一步是这样做:

int max = a - k * c;
如果
a
,那么
k==1
k*c=c=a-b
,依此类推

a - k * c = a - (a - b) = a - a + b = b
哪个是正确的最大值,因为
a
。否则,如果
a>=b
,则
k==0

a - k * c = a - 0 = a

这也是正确的最大值。

以下是这些行的作用:


c是a-b。如果c为负数,a使用移位思想提取他人张贴的标志,这里有另一种方法:

max (a, b) = new[] { a, b } [((a - b) >> 31) & 1]
这将两个数字推入一个数组,数组元素给出的最大数字的索引是两个数字之差的符号位

请注意:

  • 差异
    (a-b
    )可能溢出
  • 如果数字无符号且
    >
    运算符指向逻辑右移,则不需要
    &1
  • 这是基于相同的技术,但它是不太“明显”这里我在做什么。“abs”操作看起来像是在比较某个符号,但我在这里利用了这样一个事实,即sqrt()总是会返回正平方根,所以我将其全部平方(a-b),然后再次平方根,加上a+b并除以2

    你会发现它总是有效的:例如用户的例子10和5,你得到sqrt(100+25-100)=5,然后加10和5得到20,除以2得到10


    如果我们使用9和11作为我们的数字,我们将得到(sqrt(121+81-198)+11+9)/2=(sqrt(4)+20)/2=22/2=11

    猜测我们可以将数字与它们的位比较相乘,例如:

    int max=(a>b)*a+(a<=b)*b;
    

    int max=(a>b)*a+(a以下是我认为我应该如何做这项工作。它的可读性不如你所希望的,但当你从“我如何做X而不使用明显的做X的方法”开始时,你必须有点期待。
    从理论上讲,这也放弃了一些可移植性,但您必须找到一个非常不寻常的系统来发现问题

    #define BITS (CHAR_BIT * sizeof(int) - 1)
    
    int findmax(int a, int b) { 
        int rets[] = {a, b};
        return rets[unsigned(a-b)>>BITS];
    }
    
    与问题中所示的方法相比,这确实有一些优势。首先,它计算正确的移位大小,而不是硬编码为32位整数。其次,对于大多数编译器,我们可以预期所有乘法都在编译时发生,因此在运行时剩下的只是简单的位操作(减法和移位)简言之,这几乎可以肯定是相当快的,即使在最小的微控制器上也是如此,因为最初的微控制器使用的乘法必须在运行时发生,所以虽然在台式机上可能相当快,但在小型微控制器上通常会相当慢

    int max(int i, int j) {
        int m = ((i-j) >> 31);
        return (m & j) + ((~m) & i);
    }
    
    这个解决方案避免了乘法运算。 m将是0x00000000或0xffffffff

    静态int mymax(int a,int b)


    如果b>a,那么(a-b)将为负,符号将返回-1,通过添加1我们得到索引0,即b,如果b=a,那么a-b将为0,+1将给出索引1,因此无论我们是返回a还是b,当a>b时,a-b将为正,符号将返回1,添加1我们得到存储a的索引2。

    最简单的答案如下

    #include <math.h>
    
    int Max(int x, int y)
    {
        return (float)(x + y) / 2.0 + abs((float)(x - y) / 2);
    }
    
    int Min(int x, int y)
    {
        return (float)(x + y) / 2.0 - abs((float)(x - y) / 2);
    }
    
    #包括
    最大整数(整数x,整数y)
    {
    返回(浮动)(x+y)/2.0+abs(浮动)(x-y)/2;
    }
    最小整数(整数x,整数y)
    {
    返回(浮动)(x+y)/2.0-abs(浮动)(x-y)/2;
    }
    
    只有一种方法

     public static int Min(int a, int b)
      {
       int dif = (int)(((uint)(a - b)) >> 31);
       return a * dif + b * (1 - dif);
      }
    

    return (a>=b)?b:a;
    

    问题中描述的逻辑可以解释为,如果第一个数字小于0,则将减去0,否则将从第一个数字中减去差值,得到第二个数字。 我又找到了一个数学解,我认为它更容易理解这个概念

    将a和b视为给定的数字

    c=|a/b|+1;
    d=(c-1)/b;
    smallest number= a - d*(a-b);
    
    同样,这个想法是找到k,它是威瑟尔0或1,然后用两个数字的差乘以它。最后这个数字应该从第一个数字中减去,得到两个数字中较小的一个。
    另外,如果第二个数字为零,此解决方案将失败。我提供的代码用于查找两个数字之间的最大值,数字可以是任何数据类型(整数、浮点)
        {
            int[] arr;
            arr = new int[3];
            arr[0] = b;
            arr[1] = a;
            arr[2] = a;
            return arr[Math.Sign(a - b) + 1];
    
        }
    
    #include <math.h>
    
    int Max(int x, int y)
    {
        return (float)(x + y) / 2.0 + abs((float)(x - y) / 2);
    }
    
    int Min(int x, int y)
    {
        return (float)(x + y) / 2.0 - abs((float)(x - y) / 2);
    }
    
     public static int Min(int a, int b)
      {
       int dif = (int)(((uint)(a - b)) >> 31);
       return a * dif + b * (1 - dif);
      }
    
    return (a>=b)?b:a;
    
    c=|a/b|+1;
    d=(c-1)/b;
    smallest number= a - d*(a-b);
    
    double findmax(double a, double b)
    {
        //find the difference of the two numbers
        double diff=a-b;
        double temp_diff=diff;
        int int_diff=temp_diff;
        /*
          For the floating point numbers the difference contains decimal
          values (for example 0.0009, 2.63 etc.) if the left side of '.' contains 0 then we need
          to get a non-zero number on the left side of '.'
        */
        while ( (!(int_diff|0)) && ((temp_diff-int_diff)||(0.0)) )
        {
           temp_diff = temp_diff * 10;
           int_diff = temp_diff;
        }
        /*
          shift the sign bit of variable 'int_diff' to the LSB position and find if it is 
          1(difference is -ve) or 0(difference is +ve) , then multiply it with the difference of
          the two numbers (variable 'diff') then subtract it with the variable a.
        */
        return a- (diff * ( int_diff >> (sizeof(int) * 8 - 1 ) & 1 ));
    }
    
    int getMax(int a, int b){
        return (a+b+((a-b)>>sizeof(int)*8-1|1)*(a-b))/2;
    }
    
    max
    = ( max + max ) / 2
    = ( max + (min+differenceOfMaxMin) ) / 2
    = ( max + min + differenceOfMaxMin ) / 2
    = ( max + min + | max - min | ) ) / 2
    
    getMax(a, b)
    = ( a + b + absolute(a - b) ) / 2
    
    absolute(x)
    = x [if 'x' is positive] or -x [if 'x' is negative]
    = x * ( 1 [if 'x' is positive] or -1 [if 'x' is negative] )
    
    absolute(x)
    = x * ( 1 [if 'x' is positive] or -1 [if 'x' is negative] )
    = x * ( ( x >> (numberOfBitsInInteger-1) ) | 1 )
    = x * ( ( x >> ((numberOfBytesInInteger*bitsInOneByte) - 1) ) | 1 )
    = x * ( ( x >> ((sizeOf(int)*8) - 1) ) | 1 )
    
    getMax(a, b)
    = ( a + b + absolute(a - b) ) / 2
    = ( a + b + ((a-b) * ( ( (a-b) >> ((sizeOf(int)*8) - 1) ) | 1 )) ) / 2
    
    int getMax(int a, int b){
        int i[] = {a, b};
        return i[( (i[0]-i[1]) >> (sizeof(int)*8 - 1) ) & 1 ];
    }
    
    #include<stdio.h>
    main()
    {
            int num1,num2,diff;
            printf("Enter number 1 : ");
            scanf("%d",&num1);
            printf("Enter number 2 : ");
            scanf("%d",&num2);
            diff=num1-num2;
            num1=abs(diff);
            num2=num1+diff;
            if(num1==num2)
                    printf("Both number are equal\n");
            else if(num2==0)
                    printf("Num2 > Num1\n");
            else
                    printf("Num1 > Num2\n");
    }
    
    int max1(int a, int b) {
      static const size_t SIGN_BIT_SHIFT = sizeof(a) * 8 - 1;
      int mask = (a - b) >> SIGN_BIT_SHIFT;
      return (a & ~mask) | (b & mask);
    }
    
    int max2(int a, int b) {
      static const size_t SIGN_BIT_SHIFT = sizeof(a) * 8 - 1;
      int mask = (a - b) >> SIGN_BIT_SHIFT;
      return a ^ ((a ^ b) & mask);
    }
    
    static void Main()
    {
    
        Console.Write(" write the first number to compare: ");
        double first_Number = double.Parse(Console.ReadLine());
    
        Console.Write(" write the second number to compare: ");
        double second_Number = double.Parse(Console.ReadLine());
    
        double compare_Numbers = Math.Max(first_Number, second_Number);
        Console.Write("{0} is greater",compare_Numbers);
    
    }
    
    function (x, y) {
        let z = (x - y) ** 2;
        z = z ** .5;
        return (x + y + z) / 2
    }