浅谈lowbit运算

在这里插入图片描述

今天一起来简单了解一下lowbit()运算,小白技术水平有限,只是简单介绍一下,欢迎大佬指教!

介绍

首先来简单介绍一下lowbit(),lowbit(x)的值是x的二进制表达式中最低位的1所对应的十进制值。通俗点来说,lowbit(x)是将 x 转化成二进制数之后,只保留最低位(从右往左数,第一位)的1及其后面的0,截断前面的内容,然后再转成10进制数。

举个列子,lowbit(6) = 2,lowbit(7) = 1
原数二进制lowbit(x)
611021 = 2
711120 = 1
原理(可能讲解的很不到位,甚至出错,欢迎大佬指教)
  1. x=1,lowbit(1) = 1;
    (原码与补码的转换,小伙伴们可以自行了解一下啊)
原数原码/补码
10000 0001
-11111 1111
	0 0 0 0 0 0 0 1 
&	1 1 1 1 1 1 1 1
————————————————————————
=	0 0 0 0 0 0 0 1

lowbit(1) = 20 = 1;

  1. x=6,lowbit(6) = 2;
原数原码/补码
60000 0110
-61111 1010
	0 0 0 0 0 1 1 0
&	1 1 1 1 1 0 1 0
————————————————————————
=	0 0 0 0 0 0 1 0

lowbit(6) = 21 = 2;

总结

lowbit(x)=2p(p是指将x转化为二进制之后从右往左数第一个1的位置)
比如1的二进制写作0000001,1处于第0位,所以p=0, 20=1, 所以lowbit(1)=1;
比如6的二进制写作0000110,1处于第1位,所以p=1, 21=2, 所以lowbit(6)=2。

lowbit函数的实现方式

首先,先简单介绍一下两种运算:^运算(异或运算)与 &运算(与运算):

^运算(异或运算)

运算规则:
0^0=0; 0^1=1; 1^0=1; 1^1=0;

&运算(与运算)

运算规则:

0&0=0;0&1=0;1&0=0;1&1=1

lowbit函数实现方式一:

x&-x

下面是两个简单的列子(小伙伴们可以参考一下):

1. x=1,lowbit(1) = 1;

(原码与补码的转换,小伙伴们可以自行了解一下啊)

原数原码/补码
10000 0001
-11111 1111
	0 0 0 0 0 0 0 1 
&	1 1 1 1 1 1 1 1
————————————————————————
=	0 0 0 0 0 0 0 1

lowbit(1) = 20 = 1;

2. x=6,lowbit(6) = 2;
原数原码/补码
60000 0110
-61111 1010
	0 0 0 0 0 1 1 0
&	1 1 1 1 1 0 1 0
————————————————————————
=	0 0 0 0 0 0 1 0

lowbit(6) = 21 = 2;

lowbit函数实现方式二:

x&(x^(x-1))

下面举两个例子,来简单说明一下:

1. x=1,lowbit(1) = 1;
原数原码/补码x-1
10000 00010000 0000
第一步
	x-1可以直接按照二进制减法,或者转化为x+(-1)
	
	按照减法做:
	1 的原码:0000 0001
	
	0 0 0 0 0 0 0 1 
-	0 0 0 0 0 0 0 1
————————————————————————
=	0 0 0 0 0 0 0 0
	
	按照加法做:x+(-1)
	-1 的补码:1111 1111
	
	0 0 0 0 0 0 0 1 
+	1 1 1 1 1 1 1 1
————————————————————————
=	0 0 0 0 0 0 0 0

总之,x-1 = (1)2 - (1)2 = (0)2

接下来,进行下一步运算:x^(x-1)

第二步
	x^(x-1) :
	0 0 0 0 0 0 0 1
^	0 0 0 0 0 0 0 0
————————————————————————
=	0 0 0 0 0 0 0 1

x^(x-1) = (0000 0001)(二进制表示)	

x&(x^(x-1))

第三步
	x&(x^(x-1)) :
	0 0 0 0 0 0 0 1
&	0 0 0 0 0 0 0 1
————————————————————————
= 0 0 0 0 0 0 0 1

综上三步所述,lowbit(1) = 20 = 1;

2. x=6,lowbit(6) = 2;
原数原码/补码x-1
60000 01100000 0101
	第一步
x-1可以直接按照二进制减法,或者转化为x+(-1)

	按照减法做:
	6 的原码:0000 0110

	0 0 0 0 0 1 1 0
-	0 0 0 0 0 0 0 1
————————————————————————
=	0 0 0 0 0 1 0 1

	按照加法做:x+(-1)
	-1 的补码:1111 1111

	0 0 0 0 0 1 1 0 
+	1 1 1 1 1 1 1 1
————————————————————————
=  0 0 0 0 0 1 0 1 

总之,x-1 = (6)2 - (1)2 = (5)2

接下来,进行下一步运算:x^(x-1)

第二步
	x^(x-1) :
	0 0 0 0 0 1 1 0
^	0 0 0 0 0 1 0 1
————————————————————————
=	0 0 0 0 0 0 1 1

x^(x-1) = (0000 0011)(二进制表示)	

x&(x^(x-1))

第三步
	x&(x^(x-1)) :
	0 0 0 0 0 1 1 0
&	0 0 0 0 0 0 1 1
————————————————————————
= 0 0 0 0 0 0 1 0

综上三步所述,lowbit(6) = 21 = 2;

使用lowbit运算统计二进制数中1的个数

在这里插入图片描述
这个题是最近做到的一个题目,运用的技术就是使用lowbit运算:

public class NinthOne {

	public static void main(String[] args) {
		int result = NumberOf1(9);
		System.out.println(result);
	}
	
	 public static int NumberOf1(int n)
	 {
		 int result = 0;
		 while(n!=0) {
//			 两种方法求lowbit的值都可以:n&-n 或者  n&(n^(n-1))
//			 n = n - (n & -n);
			 n = n- (n & (n ^ (n - 1)));
			 result++;
		 }
		 
		 return result;
	 }
}

在这里插入图片描述
在这里插入图片描述
本小白技术有限,lowbit 在树状数组 等问题中也有很多应用,欢迎大佬可以指教,也欢迎小伙伴们可以一起探讨,一起加油!

  • 8
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
UART串口通信_FPGA和上位机通信实验FPGA设计Verilog逻辑源码Quartus11.0工程文件. 功能描述:串口通信__FPGA和上位机通信(波特率:9600bps,10个bit是1位起始位,8个数据位,1个结束) ** 操作过程:按动key2,FPGA向PC发送“da xi gua"一次,KEY1是复位按键。 ** 字符串(串口调试工具设成字符格式接受和发送方式),FPGA接受(0到9)后显示在7段数码管上。 module uart(clk,rst,rxd,txd,en,seg_data,key_input); input clk,rst; input rxd; //串行数据接收端 input key_input; //按键输入 output[7:0] en; output[7:0] seg_data; reg[7:0] seg_data; output txd; //串行数据发送端 ////////////////////inner reg//////////////////// reg[15:0] div_reg; //分频计数器,分频值由波特率决定。分频后得到频率8倍波特率的时钟 reg[2:0] div8_tras_reg; //该寄存器的计数值对应发送时当前位于的时隙数 reg[2:0] div8_rec_reg; //该寄存器的计数值对应接收时当前位于的时隙数 reg[3:0] state_tras; //发送状态寄存器 reg[3:0] state_rec; //接受状态寄存器 reg clkbaud_tras; //以波特率为频率的发送使能信号 reg clkbaud_rec; //以波特率为频率的接受使能信号 reg clkbaud8x; //以8倍波特率为频率的时钟,它的作用是将发送或接受一个bit的时钟周期分为8个时隙 reg recstart; //开始发送标志 reg recstart_tmp; reg trasstart; //开始接受标志 reg rxd_reg1; //接收寄存器1 reg rxd_reg2; //接收寄存器2,因为接收数据为异步信号,故用两级缓存 reg txd_reg; //发送寄存器 reg[7:0] rxd_buf; //接受数据缓存 reg[7:0] txd_buf; //发送数据缓存 reg[2:0] send_state; //这是发送状态寄存器 reg[19:0] cnt_delay; //延时去抖计数器 reg start_delaycnt; //开始延时计数标志 reg key_entry1,key_entry2; //确定有键按下标志 //////////////////////////////////////////////// parameter div_par=16'h145; //分频参数,其值由对应的波特率计算而得,按此参数分频的时钟频率是波倍特率的8 //倍,此处值对应9600的波特率,即分频出的时钟频率是9600*8 (CLK 50M) //////////////////////////////////////////////// assign txd=txd_reg; //assign lowbit=0; assign en=0; //7段数码管使能信号赋值 always@(posedge clk ) begin if(!rst) begin cnt_delay<=0; start_delaycnt<=0; end else if(start_delaycnt) begin if(cnt_delay!=20'd800000) begin cnt_delay<=cnt_delay+1'b1; end else begin cnt_delay<=0;

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值