我在思考如何在不使用if
语句或 abs()
的情况下获取整数的绝对值。一开始我尝试使用左移位操作符(<<
),试图将负号移到范围之外,然后再右移回来,但很遗憾这种方法对我不起作用。请告诉我为什么它不起作用以及其他替代方法。
我在思考如何在不使用if
语句或 abs()
的情况下获取整数的绝对值。一开始我尝试使用左移位操作符(<<
),试图将负号移到范围之外,然后再右移回来,但很遗憾这种方法对我不起作用。请告诉我为什么它不起作用以及其他替代方法。
来自位操作技巧:
int v; // we want to find the absolute value of v
unsigned int r; // the result goes here
int const mask = v >> sizeof(int) * CHAR_BIT - 1;
r = (v + mask) ^ mask;
CHAR_BIT
是char类型中的位数,通常为8。它在limits.h中定义。对于32位整数,该表达式返回31。 - Hasturkunint abs(int v)
{
return v * ((v>0) - (v<0));
}
这段代码将v
的值乘以-1
或1
,从而获得绝对值abs(v)
。因此,括号内将是-1
或1
之一。
如果v
为正数,则表达式(v>0)
为真,并且其值为1
,而(v<0)
为假(false)(false的值为0)。因此,当v
为正数时,((v>0) - (v<0)) = (1-0) = 1
。整个表达式为:v * (1) == v
。
如果v
为负数,则表达式(v>0)
为假,并且其值为0
,而(v<0)
为真(true)(true的值为1)。因此,对于负数v
,((v>0) - (v<0)) = (0-1) = -1
。整个表达式为:v * (-1) == -v
。
当v == 0
时,(v<0)
和(v>0)
都将计算为0,结果为:v * 0 == 0
。
v * ((v>0) - (v<0))
将是等效的且更易于阅读,不是吗? - Jens Gustedt无分支:
int abs (int n) {
const int ret[2] = { n, -n };
return ret [n<0];
}
注意 4.7 整数转换 / 4: [...] 如果源类型是 bool 类型,值 false 将被转换为零,值 true 将被转换为一。
我在C语言中尝试了这段代码,它可以运行。
int abs(int n){
return n*((2*n+1)%2);
}
希望这个答案能对您有所帮助。2*n + 1
会溢出,并且对于大数字它将无效。 - phuclvn * (n % 2);
呢? - Narek Ghazaryan0
。 - havakok假设使用32位有符号整数(Java),可以编写以下代码:
public static int abs(int x)
{
return (x + (x >> 31)) ^ (x >> 31);
}
没有乘法,也没有分支。
顺便说一下,return (x ^ (x >> 31)) - (x >> 31);
同样可以工作,但它已经被专利保护了。是的!
注意:这段代码可能比条件语句(8位版本)慢10倍以上。这在硬件编程系统C等方面可能有用。
c
而不是 java
的。-1。 - Box Box Box Box我之前没有看到这个。对于二进制补码表示和32位整数
( n >> 31 | 1 ) * n
n
是负数,并且在使用>>
运算符时系统进行零填充,那么n >> 31
位将会是0....0001
,导致"绝对值"成为一个负数。根据C11 6.5.7p5规定(https://port70.net/~nsz/c/c11/n1570.html#6.5.7p5):"如果E1具有有符号类型并且具有负值,则结果值是实现定义的。" - Andrew Henleint abs(int n)
{
return sqrt(n*n);
}
n
值,它会溢出,并且如果浮点类型不包含两倍于 int
的精度,则无法正确工作。 - phuclv无分支或乘法:
int abs(int n) {
int mask = n >> 31;
return (mask & -n) | (~mask & n);
}
以下是另一种方法,不使用abs()
或任何逻辑/条件表达式:假设此处的int为32位整数。这个想法相当简单:(1-2*符号位)
将把符号位=1/0转换为-1/1
。
unsigned int abs_by_pure_math( int a ) {
return (1 - (((a >> 31) & 0x1) << 1)) * a;
}
float absB(float n) {
return n - n * 2.0f * ( n < 0.0f );
}