我正在寻找一个表达式,它使我能够编写具有以下属性的表达式:
f(x, SOME_CONSTANT) -> returns -x (or any negative value)
f(x, SOME_CONSTANT2) -> returns x (or any positive value)
f(0, SOME_CONSTANT) -> returns 0
f(0, SOME_CONSTANT2) -> returns 0
没有乘法/分支,尽可能高效。
乍一看 x ^ 0x80000000 似乎是一个候选,但当 x 为 0 时它不起作用。
好吧,我终于弄清楚如何有效地做到这一点:
Java:
int f(int x, int y) {
return (((x >> 31) | ((unsigned)-x >> 31)) ^ y) - y;
}
C/C++:
int f(int x, int y) {
return (((x > 0) - (x < 0)) ^ y) - y;
}
上面这些函数返回-sgn(x)
y is -1 and sgn(x)
否则。
或者,如果我们只需要处理 -2^31(最小无符号 int 值)以外的每个值,并且具有保留绝对值的优点,则这是翻转符号的函数,具体取决于变量 y:
int f(int x, int y) {
return (x ^ y) - y; // returns -x for y == -1, x otherwise
}
推导:
-x == ~x + 1 == (x ^ 0xFFFFFFFF) + 1 == (x ^ -1) + 1 == (x ^ -1) - (-1)。用 y 代替 -1,我们得到一个二变量公式,它有一个有趣的属性,如果 y 设置为 0,则返回不变的 x,因为 (x ^ 0) 和减去 0 都不会改变结果。现在的极端情况是,如果 x 等于 0x8000000,则此公式不起作用。这可以通过应用 sgn(x) 函数来解决,所以我们有(sgn(x) ^ y) - y)
。最后,我们用不使用分支的众所周知的公式替换 sgn(x) 函数。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)