package com.e2u.bit;
public class BitTwiddling
{
public static int min(int a, int b)
{
int diff = b - a;
// b < a: a + (diff & -1) = a + diff = a + (b - a) = b
// b > a: a + (diff & 0) = a + 0 = a
return a + (diff & (diff >> 31));
}
public static int max(int a, int b)
{
int diff = b - a;
// b < a: b - (diff & -1) = b - diff = b - (b - a) = a
// b > a: b - (diff & 0) = b - 0 = b
return b - (diff & (diff >> 31));
}
/**
* 正数和0的补码同原码,负数的补码是绝对值的反码加1。-1的补码表示是0xFFFFFFFF。
*
* 原码 true code
* 补码 complemental code: 负数的补码是绝对值的反码加1
* 反码 ones-complement code: 直接取反(1变0, 0变1)后的结果
*
* 1`s complement(one's complement) 指的是正数=原码,负数=反码
* 2`s complement(two's complement) 指的就是通常所指的补码
*
* @param a
* @return
*/
public static int abs(int a)
{
// 既然负数的补码是绝对值的反码+1,
// 那么负数的绝对值就是这个负数-1后的反码
// 当x为负数时 ==> x = ~|x| + 1 ==> |x| = ~(x - 1)
int temp = (a >> 31);
// a >= 0: a >> 31 = 0 --> (a + temp) ^ temp = a ^ 0 = a;
// a < 0: a >> 31 = -1(0xFFFFFFFF) --> (a + temp) ^ temp = (a - 1) ^ (-1) = ~(a - 1)
return (a + temp) ^ temp;
}
/**
* another imp of follow the pattern of cmp imp
* @param a
* @return
*/
public static int absOR(int a)
{
return ((a >> 31) & (-a)) | (((-a) >> 31) & a);
}
/**
*
* Reference: HD 2-7 Sign Function
* sign(x) = (x >> 31) | (-x >>> 31)
* x >>> 31 ==> (x >> 31) & 1
* @param a
* @param b
* @return
*/
public static int cmp(int a, int b)
{
// return ((a - b) >> 31) | ((b - a) >>> 31);
//Java has the operation >>>, but in the language without >>>,
//it can be replaced by the below expression
return ((a - b) >> 31) | (((b - a) >> 31) & 1);
}
/**
* Cover the overflow cases
* @param a
* @param b
* @return
*/
public static int cmpOF(int a, int b)
{
long diff = (long)a - (long)b;
return (int) ( (diff >> 63) | (-diff >>> 63) );
}
public static void main(String[] args)
{
int[][] arrays = { { 1, 1 }, { -2, -2 }, { 0, 0 }, { 10, 20 },
{ 20, 10 }, { -10, -20 }, { -20, -10 }, { 50, -5 }, { -5, 50 },
{ Integer.MIN_VALUE, Integer.MIN_VALUE + 100 },
{ Integer.MAX_VALUE, Integer.MAX_VALUE - 100 },
{ Integer.MAX_VALUE, Integer.MIN_VALUE },
{ Integer.MIN_VALUE, Integer.MAX_VALUE }};
//min
for(int i = 0; i < arrays.length; i++)
{
System.out.printf("min(%d, %d) = %d\n", arrays[i][0], arrays[i][1],
min(arrays[i][0], arrays[i][1]));
}
//max
for(int i = 0; i < arrays.length; i++)
{
System.out.printf("max(%d, %d) = %d\n", arrays[i][0], arrays[i][1],
max(arrays[i][0], arrays[i][1]));
}
//cmp
for(int i = 0; i < arrays.length; i++)
{
System.out.printf("cmp(%d, %d) = %d\n", arrays[i][0], arrays[i][1],
cmp(arrays[i][0], arrays[i][1]));
}
//cmpOF
for(int i = 0; i < arrays.length; i++)
{
System.out.printf("cmpOF(%d, %d) = %d\n", arrays[i][0], arrays[i][1],
cmpOF(arrays[i][0], arrays[i][1]));
}
//abs
for(int i = 0; i < arrays.length; i++)
{
System.out.printf("abs(%d) = %d\n", arrays[i][0], abs(arrays[i][0]));
}
//abs
for(int i = 0; i < arrays.length; i++)
{
System.out.printf("absOR(%d) = %d\n", arrays[i][0], absOR(arrays[i][0]));
}
System.out.printf("abs(%d) = %d\n", Integer.MIN_VALUE, abs(Integer.MIN_VALUE));
System.out.printf("Math.abs(%d) = %d\n", Integer.MIN_VALUE, Math.abs(Integer.MIN_VALUE));
System.out.printf("Integer.MIN_VALUE - 1 = %d(%s)\n", Integer.MIN_VALUE - 1, Integer.toHexString(Integer.MIN_VALUE - 1));
}
}