在没有比较运算符的情况下查找 2 个数字之间的最小值
Finding minimum value between 2 numbers without comparision operators
我已经看到了以下方法,它给出了没有关系运算符的最小值 b/w 2 个数字
y + ((x - y) & ((x - y) >>(sizeof(int) * CHAR_BIT - 1)))
在这里,如果 x=6 和 y=4,x-y=2 为正数,并将该值向右移动 31 次得到 0。(因为 +ve 数字的符号位为 0(并且 eqn 变为
y + ((x-y)&0)
从上面的 eqn 中,我们得到 y 作为最小值,这是真的。
但是对于 x=4 和 y=6 的情况,x-y=-2 并将其向右移动 31 次得到 1,方程变为:
y + ((x-y)&1)
根据我的理解,-2 和 1 的位位和变为 0,eqn 给出 o/p 为 y(6( 而不是 x(4(。有人可以解释一下吗?
完整代码:https://www.geeksforgeeks.org/compute-the-minimum-or-maximum-max-of-two-integers-without-branching/
谢谢
上述网站上给出的解释是错误的。当x < y
(x - y) >> 31 = 0b1...1 (32 ones) (*)
然后
y + ((x - y) & 0b1...1) = y + (x - y) = x
(*( 请注意,负数的右移是实现定义的。通常,它执行算术右移,用最重要的数字填充所有二进制数字,该数字在二进制补码表示中1
负数。
在许多架构上,它的效率不高,速度也比"正常"方式慢。我还应该提到它不可读且非常容易出错。
例:
int foo(int x, int y)
{
return (y + ((x - y) & ((x - y) >>(sizeof(int) * CHAR_BIT - 1))));
}
int foo1(int x, int y)
{
return x > y ? y : x;
}
和生成的代码 (ARM Cortex(:
foo:
sub r0, r0, r1
and r0, r0, r0, asr #31
add r0, r0, r1
bx lr
foo1:
cmp r0, r1
movge r0, r1
bx lr
或 x86
foo:
sub edi, esi
mov eax, edi
sar eax, 31
and eax, edi
add eax, esi
ret
foo1:
cmp edi, esi
mov eax, esi
cmovle eax, edi
ret
在新标准被批准之前,有符号整数的表示是基于实现的,并且>>它们(<<是 UB(。假设平台将有符号值作为 2 的补码,那么二进制中的 -2 11111111111111111111111111111110。将其向右移动 31 次实际上可能会导致所有位集的值(等于 -1(或值为 1,具体取决于实现。它应该static_cast
到未签名才能以明确的方式转移。
相关文章:
- 比较并显示使用最小值(a,b)和最大值(a、b)升序排列的4个数字
- 使用递归的数组的最小值.这是怎么回事
- 如何创建一个函数来计算并返回平均值、最大值和最小值
- 在二维数组中查找最小值和最大值?
- 有没有办法使用递归函数找到数组中最小值的 INDEX?C++
- 程序以使用 C++ 中的 while 循环查找一组数字的最小值
- 查找数组中第一个最小值和最后一个最大值元素之间的算术平均值
- C++ 函数,用于查找传入的 N 个数字的平均值、总和、最小值和最大值
- txt 文件中浮点数的最大和最小值
- 余数运算符的等效操作,用于处理低于允许的最小值
- 需要使用模板查找数组的第二个最小和最小值
- 在没有比较运算符的情况下查找 2 个数字之间的最小值
- 如何打印用户在C++中输入的 10 个数字的最小值
- 从 3 个数字中选择最大值和最小值,C++
- 计算各种数字中的最小值倍数,并将其打印为prime
- rand()不起作用,给了我一个超出指定的最大值和最小值的数字
- 在C++中,我需要创建一个程序,该程序在输入某个数字时循环并停止,然后显示最大值和最小值
- 获取 2D 数组中数字的平均、最小值和最大值
- 使用 ifstream 读取列中随机生成的数字的文本文件,并从列表中查找最小值和最大值
- 为什么我的c++算法总是为一个数字的最小值和最大值返回相同的值