JavaScript 进制转换&位运算,了解一下?

时间: 2020-03-23阅读: 34标签: 运算

前言

在一般的代码中很少会接触到进制和位运算,但这不代表我们可以不去学习它。作为一位编程人员,这些都是基础知识。如果你没有学过这方面的知识,也不要慌,接下来的知识并不会很难。本文你将会学习到:

  • 进制转换
  • 按位操作符
  • Javascript进制转换
  • 手动实现进制转换

进制转换

以下使用常见的十进制和二进制转换作为例子,其他进制的转换也是大同小异,感兴趣可以自己琢磨下。


十进制转二进制

根据 “逢十进一” 的法则进行计数时,每十个相同的单位组成一个和它相邻的较高的单位,这种计数法叫做十进制计数法,简称十进制。这种是我们最常用的计数法。

整数

整数使用 “除二取余,逆序排列” 来转换为二进制,下面是18转换为二进制的例子:

Copy
// 除二取余 18 / 2 = 9...0 9 / 2 = 4...1 4 / 2 = 2...0 2 / 2 = 1...0 1 / 2 = 0...1 // 倒序排列 10010

就这么简单,将得出的余数逆序排列,即可得出18的二进制表示

小数

小数使用的是 “乘二取整,顺序排列”,由于方法不同需要分开计算。下面是16.125转为二进制的例子:

Copy
16 / 2 = 8...0 8 / 2 = 4...0 4 / 2 = 2...0 2 / 2 = 1...0 1 / 2 = 0...1 0.125 * 2 = 0.25 0.25 * 2 = 0.5 0.5 * 2 = 1 10000.001

将小数相乘的结果,取结果的整数顺序排列,得出小数位的二进制表示


二进制转十进制

根据 “逢二进一 ” 的法则进行计数时,每两个相同的单位组成一个和它相邻的较高的单位,这种计数法叫做二进制计数 法,简称二进制。用二进制计数时,只需用两个独立的符号“0”和“1” 来表示。

整数

整数使用 “按权相加” 法,即二进制数首先写成加权系数展开式,然后按十进制加法规则求和。下面是101010转换位十进制的例子:

Copy
2^5 2^4 2^3 2^2 2^1 2^0 1 0 1 0 1 0 ------------------------ 32 + 0 + 8 + 0 + 2 + 0 = 42

上面从右数依次是2的0次方,2的1次方,2的2次方... , 只取位数为1的结果,将它们相加就可以得到十进制。

小数

10110.11转十进制:

Copy
2^4 2^3 2^2 2^1 2^0 2^-1 2^-2 1 0 1 1 0 . 1 1 ------------------------------- 16 + 0 + 4 + 2 + 0 + 0.5 + 0.25 = 22.75

按位操作符

按位操作符(Bitwise operators) 将其操作数(operands)当作32位的比特序列(由0和1组成),前 31 位表示整数的数值,第 32 位表示整数的符号,0 表示正数,1 表示负数。例如,十进制数18,用二进制表示则为10010。按位操作符操作数字的二进制形式,但是返回值依然是标准的JavaScript数值。


按位与( AND)

对于每一个比特位,只有两个操作数相应的比特位都是1时,结果才为1,否则为0。

用法: a & b 。

Copy
9 (base 10) = 00000000000000000000000000001001 (base 2) 14 (base 10) = 00000000000000000000000000001110 (base 2) -------------------------------- 14 & 9 (base 10) = 00000000000000000000000000001000 (base 2) = 8 (base 10)

在判断一个数字奇偶时,可以使用 a & 1

Copy
function assert(n) { return n & 1 ? "奇数" : "偶数" } assert(3) // 奇数

因为奇数的二进制最后一位是1,而1的二进制最后一位也是1,通过 & 操作符得出结果为1

按位或(OR)

对于每一个比特位,当两个操作数相应的比特位至少有一个1时,结果为1,否则为0。

用法: a | b

Copy
9 (base 10) = 00000000000000000000000000001001 (base 2) 14 (base 10) = 00000000000000000000000000001110 (base 2) -------------------------------- 14 | 9 (base 10) = 00000000000000000000000000001111 (base 2) = 15 (base 10)

将浮点数向下取整转为整数,可以使用 a | 0

Copy
12.1 | 0 // 12 12.9 | 0 // 12

按位异或(XOR)

对于每一个比特位,当两个操作数相应的比特位有且只有一个1时,结果为1,否则为0。

用法: a ^ b

Copy
9 (base 10) = 00000000000000000000000000001001 (base 2) 14 (base 10) = 00000000000000000000000000001110 (base 2) -------------------------------- 14 ^ 9 (base 10) = 00000000000000000000000000000111 (base 2) = 7 (base 10)

按位非(NOT)

反转操作数的比特位,即0变成1,1变成0。

用法: ~ a

Copy
9 (base 10) = 00000000000000000000000000001001 (base 2) -------------------------------- ~9 (base 10) = 11111111111111111111111111110110 (base 2) = -10 (base 10)

通过两次反转操作,可将浮点数向下取整转为整数

Copy
~~16.125 // 16 ~~16.725 // 16

左移(Left shift)

将 a 的二进制形式向左移 b (< 32) 比特位,右边用0填充。

用法: a << b

Copy
9 (base 10): 00000000000000000000000000001001 (base 2) -------------------------------- 9 << 2 (base 10): 00000000000000000000000000100100 (base 2) = 36 (base 10)

左移一位相当于在原数字基础上乘2,利用这一特点,实现2的n次方:

Copy
function power(n) { return 1 << n } power(3) // 8

有符号右移

将 a 的二进制表示向右移 b (< 32) 位,丢弃被移出的位。

用法: a >> b

Copy
9 (base 10): 00000000000000000000000000001001 (base 2) -------------------------------- 9 >> 2 (base 10): 00000000000000000000000000000010 (base 2) = 2 (base 10)

相比之下, -9 >> 2 得到 -3,因为符号被保留了。

Copy
-9 (base 10): 11111111111111111111111111110111 (base 2) -------------------------------- -9 >> 2 (base 10): 11111111111111111111111111111101 (base 2) = -3 (base 10)

与左移相反,右移一位在原数字基础上除以2

Copy
64 >> 1 // 32

无符号右移

将 a 的二进制表示向右移 b (< 32) 位,丢弃被移出的位,并使用 0 在左侧填充。

用法: a >>> b

在非负数来说, 9 >>>2 和 9 >> 2 都是一样的结果

Copy
9 (base 10): 00000000000000000000000000001001 (base 2) -------------------------------- 9 >>> 2 (base 10): 00000000000000000000000000000010 (base 2) = 2 (base 10)

而对于负数来说,结果就大有不同了,因为 >>> 不保留符号,当负数无符号右移时,会使用0填充

Copy
-9 (base 10): 11111111111111111111111111110111 (base 2) -------------------------------- -9 >>> 2 (base 10): 00111111111111111111111111111101 (base 2) = 1073741821 (base 10)

可以使用无符号右移来判断一个数的正负

Copy
function isPos(n) { return (n === (n >>> 0)) ? true : false; } isPos(-1); // false isPos(1); // true

虽然 -1 >>> 0 不会发生右移,但 -1 的二进制码已经变成了正数的二进制码, -1 >>> 0 结果为4294967295


Javascript进制转换

toString

toString 常用于将一个变量转为字符串,或是判断一个变量的类型,例如:

Copy
let arr = [] Object.prototype.toString.call(arr) // [object Array]

你应该没想过 toString 可以用于进制转换,请看下面例子:

Copy
(18).toString(2) // 10010(base 2) (18).toString(8) // 22 (base 8) (18).toString(16) // 12 (base 16)

参数规定表示数字的基数,是 2 ~ 36 之间的整数,若省略该参数,则使用基数 10。该参数可以理解为转换后的进制表示。

parseInt

parseInt 常用于数字取整,它同样可以传入参数用于进制转换,请看下面例子:

Copy
parseInt(10010, 2) // 18 (base 10) parseInt(22, 8) // 18 (base 10) parseInt(12, 16) // 18 (base 10)

第二个参数表示要解析的数字的基数,该值介于 2 ~ 36 之间。如果省略该参数或其值为 0,则数字将以 10 为基础来解析。如果该参数小于 2 或者大于 36,则 parseInt 将返回 NaN。

记得有道面试题是这样的:

Copy
// 问:返回的结果 [1, 2, 3].map(paseInt)

接下来,我们来一步一步的看下过程发生了什么?

Copy
parseInt(1, 0) // 基数为 0 时,以 10 为基数进行解析,结果为 1 parseInt(2, 1) // 基数不符合 2 ~ 36 的范围,结果为 NaN parseInt(3, 2) // 这里以 2 为基数进行解析,但 3 很明显不是一个二进制表示,故结果为 NaN //题目结果为 [1, NaN, NaN]

手动实现进制转换

虽然 JavaScript 为我们内置了进制转换的函数,但手动实现进制转换有利于我们理解过程,提高逻辑能力。对于初学者来说也是一个很不错的练习例子。以下只简单实现非负整数的转换。

十进制转二进制

基于 “除二取余” 思路实现

Copy
function toBinary(value) { if (isNaN(Number(value))) { throw `${value} is not a number` } let bits = [] while (value >= 1) { bits.unshift(value % 2) value = Math.floor(value / 2) } return bits.join('') }

使用

Copy
toBinary(36) // 100100 toBinary(12) // 1100

二进制转十进制

基于 “取幂相加” 思路实现

Copy
function toDecimal(value) { let bits = value.toString().split('') let res = 0 while (bits.length) { let bit = bits.shift() if (bit == 1) { // ** 为幂运算符,如:2**3 为 8 res += 2 ** bits.length } } return res }

使用

Copy
toDecimal(10011) // 19 toDecimal(11111) // 33

写在最后

本文为大家介绍了进制和位运算的相关知识,旨在温故知新。我们只需要大概了解就好,因为在开发中真的用得少,至少我只用过 ~~ 来取整。而类似于~~这种取整操作还是尽量少用为好,对于其他开发者来说,可能会影响到代码可读性。

站长推荐

1.阿里云: 本站目前使用的是阿里云主机,安全/可靠/稳定。点击领取2000元代金券、了解最新阿里云产品的各种优惠活动点击进入

2.腾讯云: 提供云服务器、云数据库、云存储、视频与CDN、域名等服务。腾讯云各类产品的最新活动,优惠券领取点击进入

3.广告联盟: 整理了目前主流的广告联盟平台,如果你有流量,可以作为参考选择适合你的平台点击进入

链接: http://www.fly63.com/article/detial/8368

js精准计算

对于浮点数的四则运算,几乎所有的编程语言都会有类似精度误差的问题,只不过在 C++/C#/Java 这些语言中已经封装好了方法来避免精度的问题,而 JavaScript 是一门弱类型的语言,从设计思想上就没有对浮点数有个严格的数据类型,所以精度误差的问题就显得格外突出

JavaScript浮点数精度

0.1 + 0.2 是否等于 0.3 作为一道经典的面试题,已经广外熟知,说起原因,大家能回答出这是浮点数精度问题导致,也能辩证的看待这并非是 ECMAScript 这门语言的问题,今天就是具体看一下背后的原因。

JavaScript中双叹号(!!)作用

a默认是undefined。!a是true,!!a则是false,所以b的值是false,而不再是undefined,也非其它值,主要是为后续判断提供便利。!!一般用来将后面的表达式强制转换为布尔类型的数据(boolean),也就是只能是true或者false;

哈夫曼树的js实现

哈夫曼树是数据压缩编码算法的基础,本文使用JavaScript语言实现了该算法。算法流程:输入待编码的字符串,算法去构造哈夫曼树,从而实现对字符串的二进制压缩编码。

Js四舍五入及精度丢失问题

在JS中使用数值计算时,经常会遇到未知的结果。问题:用toFixed保留小数时,四舍五入规则不固定:常见的解决思路:将小数放大为整数,进行四舍五入后,再缩小为小数。

JS中三个点(...)

我们在看js代码时经常会出现(...)三个点的东西,它究竟是什么意思?又有何用处?下面我就给大家分享一下三个点的那些事

JavaScript中typeof运算符有什么用?

JavaScript中typeof运算符可以用来检测一个变量的类型。typeof运算符会返回一个字符串,表示未经计算的操作数的类型。typeof是一个运算符,有2种使用方式:typeof(表达式)和typeof 变量名,第一种是对表达式做运算,第二种是对变量做运算。

JS保留两位小数

以下处理结果会四舍五入:以下处理结果不会四舍五入第一种,先把小数边整数:第二种,当作字符串,使用正则匹配:注意:如果是负数,请先转换为正数再计算,最后转回负数

用javascript怎么求最小值?

JavaScript一种直译式脚本语言,是一种动态类型、弱类型、基于原型的语言,内置支持类型。通常JavaScript脚本是通过嵌入在HTML中来实现自身的功能的。

javascript逻辑运算符有哪些?

JavaScript逻辑运算符有&&(逻辑与)、||(逻辑或)、!(逻辑非)。JavaScript逻辑运算符用于测定变量或值之间的逻辑。

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!

文章投稿关于web前端网站点搜索站长推荐网站地图站长QQ:522607023

小程序专栏: 土味情话心理测试脑筋急转弯幽默笑话段子句子语录成语大全运营推广