查找两个数字的最大值。您不应使用if-else或任何其他比较运算符。我在在线公告板上发现了这个问题,所以我认为我应该在StackOverflow中询问
示例输入: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或任何其他比较运算符。我在在线公告板上发现了这个问题,所以我认为我应该在StackOverflow中询问
示例输入: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;
}
Answers:
int getMax(int a, int b) {
int c = a - b;
int k = (c >> 31) & 0x1;
int max = a - k * c;
return max;
}
让我们对此进行剖析。第一行看起来很简单-它存储了a
和的差b
。如果为负,则该值为a < b
负;否则为非负。其实这里有一个错误-如果数字的差异a
,并b
是如此之大,它不适合到一个整数,这将导致不确定的行为-哎呀!因此,我们假设这里没有发生这种情况。
在下一行中
int k = (c >> 31) & 0x1;
想法是检查的值是否c
为负。在几乎所有现代计算机中,数字都是以二进制补码的格式存储的,如果数字为正,则数字的最高位为0,如果数字为负,则数字的最高位为1。此外,大多数整数是32位。 (c >> 31)
将数字下移31位,将数字的最高位留在最低位。取该数字并将其与1(其二进制表示除最后一位以外的所有地方均为0)进行下一步的操作将擦除所有较高位,并为您提供最低位。由于的最低位c >> 31
是的最高位c
,因此读取的最高位c
为0或1。由于最高位是1且iffc
是1,因此这是一种检查是否为c
是负数(1)还是正数(0)。将此推理与上述内容结合使用,k
如果为1 ,则为1 a < b
,否则为0。
最后一步是这样做:
int max = a - k * c;
如果a < b
,则k == 1
和k * c = c = a - b
,依此类推
a - k * c = a - (a - b) = a - a + b = b
自以来,这是正确的最大值a < b
。否则,如果a >= b
,则k == 0
和
a - k * c = a - 0 = a
这也是正确的最高
max = a + (c >> 31) * c
开始了: (a + b) / 2 + |a - b| / 2
(3 + 2) / 2 + |3 - 2| / 2 = 2 + 0 = 2 != 3
。
使用按位黑客
r = x ^ ((x ^ y) & -(x < y)); // max(x, y)
如果知道这一点,INT_MIN <= x - y <= INT_MAX,
则可以使用以下方法,该方法速度更快,因为(x - y)
只需要评估一次即可。
r = x - ((x - y) & ((x - y) >> (sizeof(int) * CHAR_BIT - 1))); // max(x, y)
(sqrt( a*a + b*b - 2*a*b ) + a + b) / 2
这是基于与mike.dld解决方案相同的技术,但是在这里我所做的事情不太“明显”。“ abs”操作看起来像您在比较某物的符号,但是我在这里利用了sqrt()总是返回正平方根的事实,因此我对(ab)进行平方运算,然后将其全部写出,然后平方再次生根,添加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
这就是我认为自己会做的事情。它的可读性不尽如人意,但是当您从“如何在不使用X的明显方式下做X的情况下开始时,您就必须对此有所期待。从理论上讲,这也放弃了某些可移植性,但是您d必须找到一个非常不寻常的系统才能看到问题。
#define BITS (CHAR_BIT * sizeof(int) - 1)
int findmax(int a, int b) {
int rets[] = {a, b};
return rets[unsigned(a-b)>>BITS];
}
确实比问题中显示的优点有一些优势。首先,它计算出正确的移位大小,而不是为32位整数硬编码。其次,对于大多数编译器,我们可以预期所有乘法都会在编译时发生,因此在运行时剩下的只是琐碎的位操作(减法和移位),然后是加载和返回。简而言之,即使在最小的微控制器上,这也肯定是相当快的,因为最小的微控制器上原始的乘法必须在运行时进行,因此虽然在台式机上可能相当快,但通常会相当快。在小型微控制器上慢一点。
这些行正在执行以下操作:
c是ab。如果c为负,则a <b。
k是c的第32位,它是c的符号位(假定为32位整数。如果在具有64位整数的平台上执行此代码将不起作用)。它向右移了31位,以删除最右边的31位,将符号位保留在最右边,然后再将其与1相加,以删除所有的位(如果c为负,则将用1填充)。因此,如果c为负,则k将为1;如果c为正,则k将为0。
那么max = a-k * c。如果c为0,则意味着a> = b,因此max为a-0 * c = a。如果c为1,则意味着a <b,然后a-1 * c = a-(a-b)= a-a + b = b。
总体而言,它只是使用差异的符号位来避免使用大于或小于的运算。说这个代码没有使用比较,说实话有点傻。c是比较a和b的结果。该代码只是不使用比较运算符。您可以在许多汇编代码中执行类似的操作,只需减去数字,然后根据状态寄存器中设置的值进行跳转。
我还应该补充一点,所有这些解决方案都假设两个数字是整数。如果它们是浮点数,双精度数或更复杂的值(BigInts,Rational数等),那么您实际上必须使用比较运算符。比特技巧通常不会做到这些。
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] )
在整数正数中,第一位(符号位)为-0;如果为负,则为-1。通过将位右移(>>),可以捕获第一位。
在右移期间,空白空间由符号位填充。因此01110001 >> 2 = 00011100,而10110001 >> 2 = 11101100。
结果,对于8位数字,移位7位将产生-1 1 1 1 1 1 1 1 [0或1]表示负数,或0 0 0 0 0 0 0 0 [0或1]表示正数。
现在,如果对00000001(= 1)执行“或”运算,则负数将产生11111111(= -1),而正数将产生00000001(= 1)。
所以,
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");
}
我提供的代码用于查找两个数字之间的最大值,这些数字可以是任何数据类型(整数,浮点数)。如果输入数字相等,则该函数返回该数字。
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 ));
}
描述
符号位被另存为存储器中的最高有效位(MSB)。如果MSB为1,反之亦然。要检查MSB是1还是0,我们将MSB移到LSB位置,然后按位&移至1,如果结果为1,则数字为-ve否则为no。是+ ve。该结果是通过以下语句获得的:
int_diff >>(sizeof(int)* 8-1)&1
为了从MSB到LSB获得符号位,我们将其右移至k-1位(其中k是将整数保存在存储器中所需的位数,具体取决于系统的类型)。这里k = sizeof(int)* 8,因为sizeof()给出保存整数以获得no所需的字节数。的位,我们将其乘以8。在右移后,我们将按位&乘以1以得到结果。
现在获得结果后(让我们假设它为r)为1(对于-ve diff)和0(对于+ ve diff),我们将结果乘以两个数字的差,逻辑如下:
现在剩下两个要点:1.使用while循环和2.为什么我使用变量'int_diff'作为整数。为了正确回答这些问题,我们必须了解一些要点:
这是几种位旋转方法,以获取两个整数值的最大值:
方法1
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);
}
说明:
a > b
然后a - b
是正的,因而符号位为0
,和掩模是0x00.00
。否则,a < b
这样a - b
为负,符号位1
和移位后,我们得到的面具0xFF..FF
0xFF..FF
,~mask
则为0x00..00
,然后该值为0
。否则~mask
为0xFF..FF
和,值为a
0xFF..FF
,则该值为b
。否则,mask
为0x00..00
,值为0
。最后:
a >= b
那a - b
是肯定的,我们得到max = a | 0 = a
a < b
再a - b
是负的,我们得到max = 0 | b = b
方法2
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);
}
说明:
a > b
掩码为0x00..00
,则掩码为0xFF..FF
0x00..00
,(a ^ b) & mask
则为0x00..00
0xFF..FF
,(a ^ b) & mask
则为a ^ b
最后:
a >= b
得到,我们得到a ^ 0x00..00 = a
a < b
得到,我们得到a ^ a ^ b = b
//在C#中,您可以使用数学库执行最小或最大函数
使用系统;
类NumberComparator {
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);
}
}
int a=151;
int b=121;
int k=Math.abs(a-b);
int j= a+b;
double k1=(double)(k);
double j1= (double) (j);
double c=Math.ceil(k1/2) + Math.floor(j1/2);
int c1= (int) (c);
System.out.println(" Max value = " + c1);
<
。