美文网首页数据结构和算法分析
二进制位运算实战(1)-开发一个进制转换工具

二进制位运算实战(1)-开发一个进制转换工具

作者: 字节武装 | 来源:发表于2020-04-10 11:30 被阅读0次

从这篇文章你将了解到什么? 
ArrayBuffer的作用 
左位移和右位移运算的使用 
按位与运算的使用

之前介绍了二进制相关的知识 二进制转十进制心算大法, 本篇将使用JavaScript开发一个相关的可视化工具,实现十进制和二进制之间的自动转换。

当然,醉翁之意不在酒。在开发的过程中熟悉二进制的位运算才是本篇的关注点。

转换工具介绍

下面来看看这个可视化工具。

输入一个十进制的正整数(32位无符号整数), 我们会将该数字的二进制展示到一个表格中。

表格由32个单元格组成, 因为1字节=8字位, 所以单元格按八个一组来划分。

比如, 输入一个数字7, 对应的二进制就是111,那么表格就应该是下面这样:

每个单元格上的二进制数字都可以在0和1之间切换, 对应的也会计算出这组二进制数代表的十进制数。

比如, 我们把下图选中的单元格从0切换为1,那么对应的十进制数也会跟着变为263:

ArrayBuffer介绍

下面我们用数字263作为例子,讲讲如何使用位运算操作字节流的方式实现代码。

首先,初始化的时候,我们会把263这个数字放入一个数组,然后把这个数组转为字节流存放到ArrayBuffer内存当中 。

如图,下方的矩形ArrayBuffer表示一段内存,但是我们不能直接操作它。

这时候我们就要用到JS里的TypedArray来访问这一段内存,MDN把TypedArray称为“Multiple views on the same data”。

我们可以使用Uint32Array,Uint8Array等等这些“View”来对ArrayBuffer内存进读写。

这样一来,我们的“十进制展示区” 和“二进制展示区”都可以从同一块内存中读取数据,不用浪费另外的数组空间去存放一大堆的0和1。

另外,在改变“二进制展示区”单元格数值时,我们可以直接对ArrayBuffer内存中的数据进行写操作,省去了很多麻烦。

下面请看代码,我们使用Uint32Array来表示“十进制展示区” 。

let target = new Uint32Array([263])

将数组[263]转为字节流,再读取为一个由32位无符号字节组成的数组,于是变量target赋值的数组就是[263]。target[0]就是图中“十进制展示区”的263。

我们使用Uint8Array来表示“二进制展示区”。 

let bytes = new Uint8Array(target.buffer)

通过target.buffer可以读取到内存中存放的字节流,将其读取为一个由8位无符号字节组成的数组,得到的bytes数组就是[7,1,0,0], 对应的二进制数组就是[0000111,00000001, 00000000, 00000000]。

接下来我们要将bytes数组显示到“二进制展示区”中。

因为有32个单元格, 我们从第0格遍历到第31格, 每个单元格都是通过getBit方法从bytes数组中获取对应的二进制数值。

function writeBits() {   

    for (var i = 0; i < 32; i++) {     

        单元格[i].textContent = getBit(i);   

    }

}

下面是getBit的具体实现代码。

function getBit(bit) {   

    return bytes[bit >> 3] & (0x1 << (bit & 0x7)) ? 1 : 0;

}

我们一段段来解释下。

“bit>>3”分组

“>>”是右位移运算符,如果n是整数,那么n>>3效果等同n除以8取除数,可以用于分组;

“bit&7”求余

如果n是整数,n&7效果等同n除以8取余数,可以用于确定n在所属分组中的位置;

“&”运算和“<<”运算

我们知道按位与运算的规则是下面这样:

1&1=1

0&1=0

1&0=0

0&0=0

也即是说, 如果我们想要知道二进制数字"0100 0n01"中的n是0还是1,可以这样:

0x01000n01 & 0x00000100

如果结果等于0,那么n的值就是0;如果结果大于0,那么n的值就是1。

在按位与运算的规则下,0x00000100就是一个“取值器”。我们可以通过左位移运算符得到一个“取值器”。

0x1 << n的位置

把0x0000 0001中的1移动到n的位置,也就是0x0000 0100。

例子讲解

关键的位运算技巧都讲完之后,我们用一个例子来感受下。

比如我们要得到第2个单元格(从第0格算起)在bytes数组[0000111,00000001, 00000000, 00000000]中对应的数值,具体的过程就是这样:

第一步,通过2>>3=0,可以计算出第2个单元格属于第0组,也就是bytes数组中下标为0的元素。

第二步,通过2&7=0,可以计算出第2个单元格属于第一组第2个格(从第0格算起)。

第三步,制作“取值器”,0x1<<2, 得到00000100。

最后,通过"bytes[0]&取值器"判断结果是大于0还是等于0, 就可以得到第2个单元格的值了。

let res = 0x00000111 & 0x00000100 ? 1 : 0

res的值为1, 也就是第2个单元格的值为1。是不是很好玩?

未完待续......

往期回顾

二进制、八进制、十进制、十六进制数据转换

二进制转十进制心算大法

相关文章

  • 二进制位运算实战(2)-异或,按位或,按位与,取反

    从本文你将了解到什么?异或运算符的使用或运算符的使用与运算符搭配取反运算符的使用 二进制位运算实战(1)-开发一个...

  • 二进制位运算实战(1)-开发一个进制转换工具

    从这篇文章你将了解到什么?ArrayBuffer的作用左位移和右位移运算的使用按位与运算的使用 之前介绍了二进制相...

  • Java学习笔记-第一天

    位运算符 位运算是直接对二进制进行运算. 异或运算(^):相同二进制位进行运算,结果是0.不相同二进制位运算结果是...

  • LeetCode刷题笔记(九)位运算

    九. 位运算 位运算不需要转换成10进制, 因此处理速度非常快。实战常用位运算 x & 1 == 1 判断奇偶 (...

  • JAVA运算符

    1、&(按位与) &按位与的运算规则是将两边的数转换为二进制位,然后运算最终值,运算规则即(两个为真才为真)1&1...

  • 运算符

    &(按位与):&按位与的运算规则是将两边的数转换为二进制位,然后运算最终值,运算规则即(两个为真才为真)1&1=1...

  • 2019-04-24——算法基础 移位运算

    左移运算符(<<) 将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)。 按二进制形式把所有...

  • 二进制位运算符

    二进制或运算符 二进制或运算符(|)逐位比较两个运算子,两个二进制位之中只要有一个为1,就返回1,否则返回0。 上...

  • 计算机组成原理--与 或 异或运算 左移 右移运算

    与运算 (“ & ”)参与运算的两个数据,按照二进制位进行“与运算”。运算规则:0&0=0; 0&1=0; ...

  • php 与、或、异或运算

    1.与运算(&) 参加运算的两个数据,按二进制位进行“与”运算。 运算规则: 即:两位同时为“1”,结果才为“1”...

网友评论

    本文标题:二进制位运算实战(1)-开发一个进制转换工具

    本文链接:https://www.haomeiwen.com/subject/iznlmhtx.html