java absolute value_how to get absolute value of a number in java using bit manipulation

Well a negation:

-n

Is the same as the two's complement:

~n + 1

The problem is here you only want to negate if the value is < 0. You can find that out by using a logical shift to see if the MSB is set:

n >>> 31

A complement would be the same as an XOR with all 1's, something like (for a 4-bit integer):

~1010 == 1010 ^ 1111

And we can get a mask with the arithmetic right shift:

n >> 31

Absolute value says:

if n is < 0, negate it (take the complement and add 1 to it)

else, do nothing to it

So putting it together we can do the following:

static int abs(int n) {

return (n ^ (n >> 31)) + (n >>> 31);

}

Which computes:

if n is < 0, XOR it with all 1's and add 1 to it

else, XOR it with all 0's and add 0 to it

I'm not sure there's an easy way to do it without the addition. Addition involves any number of carries, even for a simple increment.

For example 2 + 1 has no carry:

10 + 1 == 11

But 47 + 1 has 4 carries:

101111 + 1 == 110000

Doing the add and carry with bitwise/bit shifts would basically just be a loop unroll and pointless.

(Edit!)

Just to be silly, here is an increment and carry:

static int abs(int n) {

int s = n >>> 31;

n ^= n >> 31;

int c;

do {

c = (n & s) << 1;

n ^= s;

} while((s = c) != 0);

return n;

}

The way it works is it flips the first bit, then keeps flipping until it finds a 0. So then the job is just to unroll the loop. The loop body can be represented by a somewhat ridiculous compound one-liner.

static int abs(int n) {

int s = n >>> 31;

n ^= n >> 31;

int c = (n & s) << 1;

c = ((n ^= s) & (s = c)) << 1; // repeat this line 30 more times

n ^= s;

return n;

}

So there's an abs using only bitwise and bit shifts.

These aren't faster than Math.abs. Math.abs just returns n < 0 ? -n : n which is trivial. And actually the loop unroll totally sucks in comparison. Just a curiosity I guess. Here's my benchmark:

Math.abs: 4.627323150634766ns

shift/xor/add abs: 6.729459762573242ns

loop abs: 12.028789520263672ns

unrolled abs: 32.47122764587402ns

bit hacks abs: 6.380939483642578ns

(The bit hacks abs is the non-patented one shown here which is basically the same idea as mine except a little harder to understand.)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值