C 解释这个不使用if-else或任何其他比较运算符查找两个整数的最大值的代码段?
找到两个数字中的最大值。不应使用if-else或任何其他比较运算符。我在网上的布告栏上发现了这个问题,所以我想我应该在网上提问 范例 输入:5,10 产出:10 我找到了这个解决方案,有人能帮我理解这些代码行吗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; } 我们开始:
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
如果我们使用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
}