如何设置/更改变量的绝对值

时间:2018-04-06 10:52:09

标签: c variables bit-manipulation sign

每个人都知道abs()函数获取变量的绝对值。是否有类似的功能或有效的方法来设置它忽略标志?

实际例子: 强制电机速度控制的最小值

if (abs(speed) < 50 && speed != 0)
{
    if (speed < 0)
        speed = -50;
    else
        speed = 50;
}

我正在寻找一个标准化的功能或一个聪明的位操作单线程。 将上述内容包含在函数或宏中是显而易见的。

4 个答案:

答案 0 :(得分:3)

它基本上是signum函数

speed = 50*sgn(speed);

这个

有一个standard function
speed = copysign(50, speed);

然而,这对整数类型来说效率不高。

sgn()功能可以使用您可以找到的各种其他方式实现here

speed = ((speed > 0) - (speed < 0))*50;

答案 1 :(得分:2)

结合您可以在SO周围找到的答案,例如Fast sign of integer in C

speed=((speed > 0) - (speed < 0)) * theNewValue;

你基本上只想保留标志,并将其乘以一个新的标准。

答案 2 :(得分:2)

您正在寻找等效于标准copysign()函数的整数。

最简单的方法是简单地将magnitude参数的绝对值乘以sign参数的符号,使用其中一种标准方法来获得:

int setabs(int magnitude, int sign)
{
     return magnitude
        * ((magnitude > 0) - (magnitude < 0))
        * ((sign > 0) - (sign < 0));
}

测试证明:

int main()
{
    return
        + (setabs(50, 1) != 50)
        + (setabs(50, 0) != 0)
        + (setabs(50, -1) != -50)
        + (setabs(-50, 1) != 50)
        + (setabs(-50, 0) != 0)
        + (setabs(-50, -1) != -50);
}

如果乘法对你来说很昂贵,那么我们可以使用两个布尔减法来制作一个稍微便宜的版本(通过相同的测试集):

int setabs(int magnitude, int sign)
{
    return magnitude
        * ((magnitude > 0 == sign >= 0) - (magnitude > 0 == sign <= 0));
}

任何位操作技术都将取决于您的平台使用哪种表示形式来表示负整数(符号幅度,一个补码,二进制补码......),并且需要将参数转换为无符号类型(或者依赖未定义的行为)。

答案 3 :(得分:0)

这取决于您的平台。由于您还没有说明您要定位的系统,因此我假设您的整数使用符号+幅度表示。 ; - )

int setabs(int sign, int magnitude)
{
    static const unsigned mask =- 0^0;
    assert(mask); // in case it's used on weird (two's complement) systems
    return (int)((unsigned)sign&mask | (unsigned)magnitude&~mask);
}

然后你可以写

speed = setabs(speed, 50);