tl;dr
int a = ...
int b = ...
int isNegative = b >>> 31; // 1 if negative, 0 if positive
int isPositive = 1 - isNegative; // 0 if negative, 1 if positive
a = isPositive * b + isNegative * a;
Signum
An easy way to achieve the task is to try to aquire some sort of signum, or more specifically a way to get a factor of
- either
0
, if b
is positive
- or
1
if b
is negative, or vice-versa.
Now, if you take a look at how int
is represented internally with its 32-bits (this is called Two's complement):
// 1234
00000000 00000000 00000100 11010010
// -1234
11111111 11111111 11111011 00101110
You see that it has the so called sign-bit on the very left, the most-significant-bit. Turns out, you can easily extract that bit with a simple bit-shift that just moves the whole bit-pattern 31
times to the right, only leaving the 32
-th bit, i.e. the sign-bit:
int isNegative = b >>> 31; // 1 if negative, 0 if positive
Now, to get the opposite direction, you simply negate it and add 1
on top of it:
int isPositive = 1 - isNegative; // 0 if negative, 1 if positive
Once you have that, you can easily construct your desired value by exploiting the fact that
- multiplication with
0
basically erases the argument (0
is an annihilator of *
)
- and addition with
0
does not change the value (0
is an identity element of +
).
So, coming back to the logic we want to achieve in the first place:
- we want
b
if b
is positive
- and we want
a
if b
is negative
Hence, we just do b * isPositive
and a * isNegative
and add them together:
a = isPositive * b + isNegative * a;
Now, if b
is positive, you will get:
a = 1 * b + 0 * a
= b + 0
= b
and if it is negative, you will get:
a = 0 * b + 1 * a
= 0 + a
= a
Other datatypes
The same approach can also be applied to any other signed data type, such as byte
, short
, long
, float
and double
.
For example, here is a version for double
:
double a = ...
double b = ...
long isNegative = Double.doubleToLongBits(b) >>> 63;
long isPositive = 1 - isNegative;
a = isPositive * b + isNegative * a;
Unfortunately, in Java you can not use >>>
directly on double
(since it usually also makes no sense to mess up the exponent and mantissa), but therefore you have the helper Double#doubleToLongBits
which basically reinterprets the double
as long
.