100118801018.com是什么网站?

位运算,相比普通的代码最大的优点就是其带来的高效性,也因此可以常在底层源码中看见它们的踪影。

本文就位运算常见的操作作一个总结,若您另有关于位运算巧妙的运用可以于底部留言区留言。

首先还是先来回顾下位操作的基础知识。(除非特别说明,否则以下都以 2 进制为例)

与运算符 "&" 是双目运算符。只有对应的两个二进位均为 1 时,结果位才为 1,否则为 0。例如:

或运算符 "|" 是双目运算符。只要对应的两个二进位有一个为 1 时,结果位就为 1。例如:

非运算符 "~" 为单目运算符。其功能是对参与运算的各二进位求反。例如:

异或运算符 "^" 是双目运算符。其功能是对参与运算的二进位相异或,即当两二进位相异时,结果为 1,相同就为 0。例如:

左移动就是向左移动 k 位,丢弃最高的 k 位,并在右端补 k 个 0,也就是常说的当前值乘以 2 的 k 次方。

右移动的原理也是相同的,右移 k 位就是当前数除以 2 的 k 次方。唯一不同的是分为逻辑右移和算术右移。

逻辑右移就是无符号移位,右移几位,就在左端补几个 0。

算术右移动是有符号移位,和逻辑右移不同的是,算术右移是在左端补 k 个最高有效位的值,如此看着有些奇特,但对有符号整数数据的运算非常有用。我们知道有符号的数,首位字节,是用来表示数字的正负(1 为负)。负数采用补码形式来存储,比如 - 26(),算术右移 1 位之后 - 13()。如若不是补最高有效位的值 1 而是补作 0 的话,右移之后就变成正数了。

i 取反再与 i 相加,相当于把所有二进制位设为 1,其十进制结果为 - 1。

~-n == n - 1,思路就是找到最低位的第一个 1,对其取反并把该位后的所有位也取反,即变为。

6. 求二进制中 1 的个数


 
 
 
 
关于第二个版本,分析如下:(摘自 ,并作稍微修改)


以十进制数 211 为例,其二进制为 ,


整个程序是一个分治的思想。第一次我们把每相邻的两位加起来,得到每两位里 1 的个数,比如前两位 10 就表示原数的前两位有 2 个 1。第二次我们继续两两相加,10+01=11,00+10=10,得到的结果是 ,它表示原数前 4 位有 3 个 1,末 4 位有 2 个 1。最后一次我们把 0011 和 0010 加起来,得到的就是整个二进制中 1 的个数。

7. 判断二进制中 1 的奇偶性

 
 
以下分析摘自 ,并作稍微修改,

第一次异或操作的结果如下:
得到的结果是一个新的二进制数,其中右起第 i 位上的数表示原数中第 i 和 i+1 位上有奇数个 1 还是偶数个 1。比如,最右边那个 0 表示原数末两位有偶数个 1,右起第 3 位上的 1 就表示原数的这个位置和前一个位置中有奇数个 1。
对这个数进行第二次异或的结果如下:
结果里的每个 1 表示原数的该位置及其前面三个位置中共有奇数个 1,每个 0 就表示原数对应的四个位置上共偶数个 1。
一直做到第五次异或结束后,得到的二进制数的最末位就表示整个 32 位数里 1 的奇偶性。
 

 

9. 不用临时变量交换两个数

 
 

 
 

 


  • 若 n 为负数,n >> 31的所有位等于 1,其值等于 - 1。表达式转化为(n ^ -1) + 1,这很好理解,负数的相反数就是对其补码取反再加 1,(n ^ -1) + 1就是在做这样的事。

 

11. 取两数的较大值

 

 


12. 判断符号是否相同

 
 

 

13. 判断一个数是不是 2 的幂

 
 
如果是 2 的幂,n - 1就是把 n 的二进制的最低的那个 1 取反为 0,并把后面的 0 全部取反为 1。
 

 
 

}

在数字通信系统中,模拟信号将转变为数字序列。

这种位序列被称为"数据流",传输过程中某个比特可能就会发出错位,1个比特的错误也会导致数据输出的灾难性(重大)误差。

图1 传输的01比特流

几乎在所有的电子设备中,我们都会发现错误,所以我们使用差错检测校正技术来获得精确的输出。

数据在传输期间(从发射器到接收器)可能被损坏。它可能受到外部噪音或其他信道的影响。在这种情况下,输入数据与接收到的输出数据不相同。这种不匹配的数据被称为"错误"。

数据错误将导致重要/安全数据的丢失。即使是数据中的一点变化也可能影响整个系统的性能。通常,数字系统中的数据传输将以比特传输的形式进行,在这种情况下,数据错误可能在0和1上发生。

在数据序列中,如果1改为0或0更改为1,则称为"位错误"。在从发射机到接收机的数据传输中,通常会出现3种类型的误差,它们是:

整个数据序列中一位比特的变化称为"单比特错误"。在串行通信系统中,单比特错误的发生概率相对较少。这种错误通常发生在并行通信系统中,由于数据在单线上以位的方式传输,每条单线上有可能产生噪声。

如果发送器到接收机的两个或多个数据序列发生变化,则称为"多比特错误"。这种错误既发生在串行型数据通信网络中,也发生在并行型数据通信网络中。

数据序列中比特集合的变化称为突发错误。计算突发误差,要从改变的第一位bit到最后一位改变的bit。

在图5,第4位和第6位之间的数字也被认为是误差。这些位被称为"突发错误"。这些突发比特在发送器和接收机之间都会发生变化,这可能会导致数据序列中的一个重大错误。这类错误发生在串行通信中,很难解决。

在数字通信系统中,误差随数据从一个通信系统传输到另一个通信系统。如果没有检测和纠正这些错误,传输的数据将会丢失。为了进行有效的通信,数据的传输应该是高度精确的,可以通过检测错误,然后再进行修正来实现。

差错检测是指在通信系统中,对从发射机发送到接收机的数据中存在的误差进行检测的过程。我们使用一些冗余码来检测这些错误,在从源(发送器)发送数据时增加数据。这些代码被称为"错误检测代码"。

差错检测编码有许多中,今天给大家介绍三种简单的,也是经典的三种:

  • 循环冗余校验(CRC)
  • 纵向冗余校验(LRC)

奇偶校验位是发送数据之前添加到发送器数据中的附加比特。

在添加奇偶校验位之前,计算数据中1或0的数目。然后,中添加一个额外的位。

在数据中添加奇偶校验位将导致数据字符串长度的变化。如果我们有一个7位数据,那么在向数据二进制字符串中添加一个奇偶校验位之后,它将变成一个8位二进制数据字符串。

奇偶校验也称为"垂直冗余检查(VRC)"。有两种类型的奇偶校验位,它们是

如果数据中1的个数为偶数,则奇偶校验位为0。例如:>奇偶校验位0。

如果数据中1的个数为奇数,则奇偶校验位为1。例如:>奇偶校验位1。

偶校验的作用就是:加上奇偶校验位后,1的个数均为偶数个。

如果数据中1的个数为奇数,则奇偶校验位为0。例:->奇偶校验位0。

如果数据中1的个数为偶数,则奇偶校验位为1。例:->奇偶校验位1。

奇校验的作用就是:加上奇偶校验位后,1的个数均为奇数个。

将奇偶校验比特添加到发射机数据的电路称为"奇偶发生器"。奇偶校验比特被发送并在接收器处被检查。如果发射机处发送的奇偶校验比特与接收端接收的奇偶校验比特不相等,则检测错误。在接收端检测奇偶校验的电路称为"奇偶校验器"。

多项式编码的思想是:将位串看成是系数为0或1的多项式。CRC校验保护的单位是数据块。数据块的大小根据实际情况而定。每一个数据块均被看作是一个二进制多项式,即所有系数均为二进制(即1或0)的多项式。

当使用多项式编码时,发送方和接收方必须预先商定一个生成多项式(Generator Polynomial)G(x)。生成多项式的最高位和最低位必须为1。

从性能上和开销上考虑,CRC均远远优于奇偶校验及算术和校验等方式。因而,在数据存储和数据通讯领域,CRC无处不再:WinRAR,通用的图像存储格式GIF、TIFF都用CRC作为检错手段。

将待发送的位串看成系数为0或1的多项式

收发双方约定一个生成多项式G(x),其最高阶和最低阶系数必须为1.

发送方用位串及G(x)进行某种运算得到校验码,并在帧的膜外加上校验码,使带校验码的帧的多项式能被G(x)整除。

接收方收到信息后,用G(x)除多项式,若有余数,则传输有错。

图8 CRC生成的过程

将要发送的数据系列左移3位,新的序列为1001000。

按模2算法,将生成的新序列除以生成多项式。

将余数多项式比特序列加到新的序列中即得发送端传送序列。

接收方可以直接用接收到的序列除以生成多项式G(x),如果余数R(x)=0,则正面传输正确。

在纵向冗余方法中,以表格格式(行和列)排列一些比特块,然后分别计算每列的奇偶校验位。这些奇偶校验位的集合就是这些比特块的校验码。

纵向冗余校验是一种逐位奇偶校验,因为我们单独计算每一列的奇偶校验。

该方法可以很容易地检测出突发错误和单比特错误,但不能检测出在同一垂直切片中发生的2位错误。

好了,三种差错检测编码介绍完了,下一步就是纠正错误的编码了。先检测,后纠正。

纠错码(error correcting code),在传输过程中发生错误后能在收端自行发现或纠正的码。仅用来发现错误的码一般常称为检错码。

纠错码也有很多种,比如说经典的分组码(Hamming Code),卷积码等。

分组码和卷积码不但可以用来纠正独立错误,而且可以用来恢复删除错误和纠正突发错误。如分组码中有里德-索洛蒙码,法尔码等;卷积码中有岩垂码及扩散卷积码等。

由于篇幅有限,如果同学们感兴趣,可以自行学习哦。班长会在后期详细下介绍纠错码。

看到这里,为班长点个赞吧!欢迎在评论区留言讨论!

}

1-1 理解数据帧的含义:
   在WebSocket协议中,数据是通过帧序列来传输的。为了数据安全原因,客户端必须掩码(mask)它发送到服务器的所有帧,当它收到一个
没有掩码的帧时,服务器必须关闭连接。不过服务器端给客户端发送的所有帧都不是掩码的,如果客户端检测到掩码的帧时,也一样必须关闭连接。
当帧被关闭的时候,可能发送状态码1002(协议错误)。

如上是基本帧协议,它带有操作码(opcode)的帧类型,负载长度,和用于 "扩展数据" 与 "应用数据" 及 它们一起定义的 "负载数据"的指定位置,
某些字节和操作码保留用于未来协议的扩展。

FIN(1位): 是否为消息的最后一个数据帧。
RSV1,RSV2,Rsv3(每个占1位),必须是0,除非一个扩展协商为非零值定义的。
Opcode表示帧的类型(4位),例如这个传输的帧是文本类型还是二进制类型,二进制类型传输的数据可以是图片或者语音之类的。(这4位转换成16进制值表示的意思如下):

0x0 表示附加数据帧
0x1 表示文本数据帧
0x2 表示二进制数据帧
0x3-7 暂时无定义,为以后的非控制帧保留
0xB-F 暂时无定义,为以后的控制帧保留

Mask(占1位): 表示是否经过掩码处理, 1 是经过掩码的,0是没有经过掩码的。

   1. 如果数据长度小于等于125的话,那么该7位用来表示实际数据长度。
   2. 如果数据长度为126到65535(2的16次方)之间,该7位值固定为126,也就是 1111110,往后扩展2个字节(16为,第三个区块表示),用于存储数据的实际长度。
   3. 如果数据长度大于65535, 该7位的值固定为127,也就是 1111111 ,往后扩展8个字节(64位),用于存储数据实际长度。

Masking-key(0或者4个字节),该区块用于存储掩码密钥,只有在第二个子节中的mask为1,也就是消息进行了掩码处理时才有,否则没有,
所以服务器端向客户端发送消息就没有这一块。

Payload data 扩展数据,是0字节,除非已经协商了一个扩展。

1-2 客户端到服务器掩码
WebSocket协议要求客户端所发送的帧必须掩码,掩码的密钥是一个32位的随机值。所有数据都需要与掩码做一次异或运算。帧头在第二个字节的第一位表示该帧是否使用了掩码。
WebSocket服务器接收的每个载荷在处理之前首先需要处理掩码,解除掩码之后,服务器将得到原始消息内容。二进制消息可以直接交付。文本消息将进行UTF-8解码

二进制位运算符知识扩展:

   右移运算符是将一个二进制位的操作数按指定移动的位数向右移动,移出位被丢弃,左边移出的空位一律补0.
首先将11转换为二进制数为 00 00 , 然后把低位的最后2个数字移出,因为该数字是正数,
所以在高位补零,则得到的最终结果为:00 00 ,转换为10进制是2.

    左移运算符是将一个二进制位的操作数按指定移动的位数向左移位,移出位被丢弃,右边的空位一律补0.
首先将3转换为二进制数为 00 00 , 然后把该数字高位(左侧)的两个零移出,其他的数字都朝左平移2位,
最后在右侧的两个空位补0,因此最后的结果是 00 00 ,则转换为十进制是12(1100 = 1*2的3次方 + 1*2的2字方)

注意1: 在使用补码作为机器数的机器中,正数的符号位为0,负数的符号位为1(一般情况下).

负数先用它的绝对值正数取它的二进制代码,7的二进制位为: 00 00 ,那么 -7的二进制位就是 取反,
取反后再加1,就变成补码。

// WS的字符串 加上 key, 变成新的字符串后做一次sha1运算,最后转换成Base64 // 输出字段数据,返回到客户端, // 输出空行,使HTTP头结束 右移运算符是将一个二进制位的操作数按指定移动的位数向右移动,移出位被丢弃,左边移出的空位一律补0. 首先将11转换为二进制数为 00 00 , 然后把低位的最后2个数字移出,因为该数字是正数, 所以在高位补零,则得到的最终结果为:00 00 ,转换为10进制是2. 左移运算符是将一个二进制位的操作数按指定移动的位数向左移位,移出位被丢弃,右边的空位一律补0. 首先将3转换为二进制数为 00 00 , 然后把该数字高位(左侧)的两个零移出,其他的数字都朝左平移2位, 最后在右侧的两个空位补0,因此最后的结果是 00 00 ,则转换为十进制是12(1100 = 1*2的3次方 + 1*2的2字方) 注意1: 在使用补码作为机器数的机器中,正数的符号位为0,负数的符号位为1(一般情况下). 比如:十进制数13在计算机中表示为,其中第一位0表示的是符号 注意2:负数的二进制位如何计算? 比如二进制的原码为 ,它的补码怎么计算呢? 首先计算它的反码是 ; 那么补码 = 反码 + 1 = 负数先用它的绝对值正数取它的二进制代码,7的二进制位为: 00 00 ,那么 -7的二进制位就是 取反, 取反后再加1,就变成补码。 // 解析前两个字节的基本数据 i += 4; // 长度一般用4个字节的整型,前四个字节一般为长整型留空的。 // 判断是否使用掩码 // 对数据和掩码做异或运算 // 否则的话 直接使用数据 // 数组转换成缓冲区来使用 // 如果有必要则把缓冲区转换成字符串来使用

这样服务器接收客户端穿过了的数据就没问题了。

}

我要回帖

更多关于 com和cn 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信