首先要明白二进制的各种操作,最常用的是移位(<<,>>),按位与(&)和按位或(&)操作。
1.判断一个二进制位的某一位是否为1。在这里以二进制数为例,判断00001000,的那一位上为1,则可以这样操作,从右向左操作,首先判断最低位是否为1,然后判断次低位是否为1,然后判断次次低位是否1,那么问题来了,如何从最低位开始获取每一位呢?我们可以这样:
获取最低位:00001000 & 0x1;结果为:0
获取次低位:(00001000>>1) & 0x1;结果为:0
获取次次低位:(00001000>>2) & 0x1;结果为:0
获取次次次最低位:(00001000>>3) & 0x1;结果为:1
.
.
由此可得若要判断一个二进制数的第 i 位是否为1: int a= (int)(00010000>>i) & 0x1 ; 然后直接判断a 的值是否等于整数1 即可。
代码如下:
public boolean is_one(int a){<span> </span>//a 表示二进制数的十进制表示法
int b=0;
for(int i=0;i<8;i++){
b=(int) (a>>i)&0x1;
if(b==1){
return true;
}
}
return false;
}
2.再说一下如何把二进制数中的某一位置1,我们还以二进制数:00001000为例,我要把最高位置1,可以这样来做:分析一下这是一个8位 的二进制数,操作最高位就需要得到一个8位的二进制数,并且这个数的最高位还得是1其余位为零。然后让这两个数进行按位或操作即可,那么思路是这样的,我们还需要得到一个最高位为1后7位为0的8位二进制数,具体计算如下:
int a = 1;
得到一个最高位为1的8位二进制数: a = a<<8;
把00001000的最高位置1:00001000 | a;
a=1 ; a<<7;
把00001000的最次高位置1:00001000 | a;
由此可得把一个二进制数 n 的第 i 位置1 : n = n | ( a << i ) ;
代码如下:
public int one(int a,int position){ //a:表示二进制数的十进制表示法,position需要把某一位置1的位置
a= a | (1<<position);
return a; //返回操作后的数
}
切入正题:下面说一下利用二进制位进行标记,获取不相同的随机数的思路
以获取100个100-500之间不同的随机数为例进行分析,100-500之间有400个数,先生成1-400之间的随机数,然后加上100得到100-500之间的随机数:代码如下
int ran = (int)Math.random*400; //1-400之间的随机数
一个int型的0在内存中占4的个字节,所以可以用32位的二进制数表示一个int,那么反过来一个int上32个位,每个位上用0表示一个整数有没有出现过;1-400之间的随机数一共有400个,400/32=12,余数为16;那么这400个数就可以用12个int加上1个Int中的16位来表示,我们可以把int存放在数组里:
int a = 400/32; //数组长度
if(400%32 ! = 0){
a++;
}
int[] arr = new int[a];
for(int i=0;i<a;i++){
arr[i]=0;
}
此时应该把int数组中有13个元素,每个元素都是0,每个元素所表示一个二进制的32位都为0,那么我们可以定义这样一种规则把所有为二进制位(映射)匹配到1-400之间的随机数上:把arr[0] 看作1-32,arr[1]看作33-64,arr[2]看作65-96....arr[12]看作385-400(arr[0]只使用了16个位), 上面我们已经得到了1-400之间了随机数了,如果我们得到的随机数 ran = 13,那么通过计算我们就可以得到ran对应的 arr [ ] 元素和ran在arr[] 元素中的位置:
int ran =(int) Math.random*400;
int position = ran/32; //ran在arr[]中的第几个元素
int value = ran%32; //ran在arr[position]的二进制表示的32个位中的位置
//以ran=13为例 通过上面的计算 13在arr[0]表示的32位二进制数中的第13位上
//ran = 35 35在arr[1]表示的32位二进制数中的第3位上
注意:二进制位是从0-31位 主意边界。
每次得到一个ran都要判断ran对应的二进制位是否为1:如果ran对应的二进制位为0,表示这个数是第一次出现,就把这个ran对应数位置的二进制的一个位置1(置1方法上面有)并把ran+100返回(我们得到的随机数是1-400之间的随机数,而我们要取得是100-500之间的随机数);如果ran对应的二进制位为0,表示这个位上出现过的这个值,此时应该(遍历二进制位)从位置arr[position]的value(二进制位的位置)向后遍历查找,找到arr[position]的value位是0的时候 返回得到的随机数:(arr[position]*32+value)+ 100;这里(arr[position]*32+value)+ 100的意思是arr[position]表示的二进制value的位置(arr[position]*32+value)的位置的值就是1-400之间对应位的值。代码如下:
public int rand(int end, int start)
{ int sum=end-start;//二进制映射区间 1-sum
int last=0;
int b = (int)(Math.random()*(end-start)); //得到440以内的随机数,100-500之间的随机数最后需要加上start
int c1=b/32;
int c2=b%32;
if(fun12(arr[c1],c2)==true){ //判断对应的二进制位上是否为0
arr[c1]=fun(arr[c1],c2);
last = start + b;
}else{
int arr1;
int c3 = c1;
int c4=c2;
int m1=0;
int m2=0;
boolean asd=false;
for(int i=c3;i<len;i++){
for(int j=c4;j<32;j++){
arr1=(int)(arr[i]>>j)&0x1;
if(arr1!=0){
continue;
}else{
asd=true;
m1=i;
m2=j;
break;
}
}
if(asd==true){
break;
}
if(asd==false){
c4=0;
}
}
if(m1==0&&m2==0){
int j1=32;
int i1=c1;
for(int i=0;i<=i1;i++){
if(i+1==c1){
j1=c2;
}
for(int j=0;j<j1;j++){
arr1=(int)(arr[i]>>j)&0x1;
if(arr1!=0){
continue;
}else{
asd=true;
m1=i;
m2=j;
break;
}
}
if(asd==true&&m1!=0){
break;
}
}
}
arr[m1]=fun(arr[m1],m2);
last = m1*32+m2+start;
}
return last;
}
//取100个100-500之间的随机数
int[] arr= new int [100];
for(int i=0;i<100;i++){
arr[i]=rand(500,100);
}
第一次写博客,敲的好累,大学里没好好学,刚学了两个月java ,感觉写了之后对自己的思路越来越明了了,应为要让大家看的更明白这需要自己好好想想如何表达,这是对二进制的应用总结,两天写了个这程序,时间紧迫啊,以后博客都放在睡觉前写 哈哈 加油~~~!