java 利用二进制位进行标记,获取不相同的随机数

首先要明白二进制的各种操作,最常用的是移位(<<,>>),按位与(&)和按位或(&)操作。

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;	//返回操作后的数
}

切入正题:下面说一下利用二进制位进行标记,获取不相同的随机数的思路

以获取100100-500之间不同的随机数为例进行分析,100-500之间有400个数,先生成1-400之间的随机数,然后加上100得到100-500之间的随机数:代码如下

int ran = (int)Math.random*400; 	//1-400之间的随机数

一个int型的0在内存中占4的个字节,所以可以用32位的二进制数表示一个int,那么反过来一个int32个位,每个位上用0表示一个整数有没有出现过;1-400之间的随机数一共有400个,400/32=12,余数为16;那么这400个数就可以用12int加上1Int中的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 ,感觉写了之后对自己的思路越来越明了了,应为要让大家看的更明白这需要自己好好想想如何表达,这是对二进制的应用总结,两天写了个这程序,时间紧迫啊,以后博客都放在睡觉前写 哈哈 加油~~~!





评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值