关于“十进制转二进制,求位数”的一点小结

题目描述:
假设有这么一个函数valueAtBit(num, bit),输入一个十进制数num,求它的二进制数的bit位是多少(注意bit应该从1算起)
以下是几种实现方法的总结:

方法一,最硬核的方法

这个方法模拟了平时我们计算二进制数的过程:

  1. num除以2,求出得商和余数(假设商为resu,余数为rest)
  2. 拿上次的商resu再除以2,求得新的商resu和本轮的余数rest
  3. 重复1、2步操作,直至商resu为0
  4. 倒序将所有的余数rest拼接即为该十进数的二进制表示

将上述过程实现成js代码如下:

function valueAtBit1(num, bit) { // 方法一
	var result = [];
	var rest = 0;
	var resu = num;
	while (resu != 0) {
		rest = resu % 2;
		resu = parseInt(resu / 2);  // 这里不要漏掉将小数转成整数
		result.push(rest);  // 这里的数组即为存储二进制数的各个位数(字符类型)
	}
	return result[bit - 1];  // 这里是应题目要求,求bit位的
}

方法二,使用js自带方法toString

function valueAtBit2(num, bit) { // 方法二
	var binary = num.toString(2);
	return binary[binary.length - bit];
}

toString接收一个参数radix(基数),表示你要把该数字对象(注意是数字对象才包含该方法,不可以是字面量)转成几进制的字符串。

方法三,使用移位操作

function valueAtBit3(num, bit) { // 方法三
	return num >> (bit - 1) & 1; //下面两种不可以, 因为只有与运算才能把除第一位以外的其他位“置零”.
	// return num >> (bit - 1) | 0;
	// return num >> (bit - 1) ^ 0;
}

这个方法是跳过求二进制数这个过程,直接求bit位的,因为移位操作只能是对二进制进行运算,所以这里可以直接用num,>>会隐式转换成二进制。
这个方法的原理是这样的:(不过如果大家看不懂以上的语句,建议在这之前先看一下位运算的基础知识哈)

  1. 先让所求位向右移到第一位,这时左边空出来的位会自动补0,先叫它“已移位的num”
  2. 让移位操作后的这个数和1相与(1的二进制除第一位左边全为0),这样相与了之后,得到的结果是除第一位之外的其他位都变为0,此时按照相与运算的运算规则:- 如果“已移位的num”第一位是0那么相与之后是0;- 如果“已移位的num”第一位是1那么相与之后是1。此时返回的结果便是所求。

可能我陈述得有点乱,不过大家可以亲测一下,原理很巧妙哦。

方法四,仅使用位相与操作

function valueAtBit4(num, bit) { // 方法四
	var binary = Math.pow(2, bit - 1);
	return (num & binary) == 0 ? 0 : 1; // ==比&优先级要高所以需要加括号
}

该方法与方法三有点相似,不过这个方法不需进行移位操作,而是先生造一个与所求位匹配的二进制数,让它们俩相与,如果结果为非零则返回1,结果为零则返回0
比如说要求29的二进制数的第3位,那么过程如下:

  1. 29 的二进制表示为 11101(这个过程由位操作符自动转换)
  2. 求第 3 位,那么生造一个二进制数 00100(除所求位为1,其他位为0),能达到这个效果的就需要用到Math.pow()这个方法了
  3. 让1、2步的这两个数进行位相与,结果是除所求位之外的其他位变为0,所求位如果原来是1则相与之后该位为1;,所求位如果原来是0则相与之后该位为0;(在本例中结果为 00100)
  4. 通过三元表达式判断结果并返回:判断第3步的结果是否为0,如果为零则返回0,如果非零则返回1(在本例中,结果00100即为十进制的4,非零,所以返回1)

我们可以验证一下结果,返回的1在原来的11101的第三位中确实是1,大家也可以验证看看其他位。原理也比较巧妙哦。
其中方法三和方法四学自牛客网的巨佬们,在这里要谢谢各位巨佬们。
同时也感谢读者们能读到最后,阿里嘎多~

发布了20 篇原创文章 · 获赞 6 · 访问量 4033

猜你喜欢

转载自blog.csdn.net/CanMoHaiYan/article/details/105174912