前端开发系列122-进阶篇之Floating point addition
本文简单说明 JavaScript 中常见的进制转换函数以及浮点数计算的注意点。
如何把任意进制的数据转换为十进制?
假设我们有二进制数据110
,如果要把该数据转换为十进制数据可以参考下面的处理过程。
110 = 1 x 2^(2) + 1 x 2^(1) + 0 x 2^(0)
= 4 + 2 + 0
= 6
在 JavaScript 语言中,我们可以通过 parseInt方法来处理上面的转换。
parseInt(string, radix)
函数将字符串转换为指定进制的整数,进制基数取值区间为[2,36]
。
其中,函数的第一个参数为要被解析的值。如果参数不是一个字符串,那么会调用toString()
来转换为字符串,此外字符串开头的空白符将会被忽略。第二个参数radix
的取值范围从 2 到 36,代表该进位系统的数字。parseInt
函数的返回值为从给定的字符串中解析出的一个整数,如果radix
的取值超出[2,36]
的范围或者第一个参数为非空格字符不能转换为数字,那么就返回 NaN
。
console.log(parseInt("110", 2));
/* 计算过程: */
/* 110 = 1 x 2^(2) + 1 x 2^(1) + 0 x 2^(0)
= 4 + 2 + 0
= 6
*/
console.log(parseInt('123', 4));
/* 计算过程 */
/* 123 = 3 x 4^(0) + 2 x 4^(1) + 1 x 4^(2)
= 3 + 8 + 16
= 27
*/
console.log(parseInt('hello', 2)); /* NaN */
console.log(parseInt('', 2)); /* NaN */
ECMAScript 5 规范不再允许 parseInt 函数的实现环境把以0字符开始的字符串作为八进制数值。根据给定的 radix,parseInt函数产生一个由字符串参数内容解析过来的整数值。字符串中开头的空白会被忽略。如果radix没有指定或者为0,参数会被假定以10为基数来解析,如果数值以字符对0x或0X开头,会假定以16为基数来解析。
parseInt
函数在具体使用的时候有一些注意点,下面通过代码来简单展示这些注意点。
/* 问题: 为什么得到的结果为1 */
/* 注解:如果 parseInt 遇到的字符不是指定 radix 参数中的数字,
它将忽略该字符以及所有后续字符,并返回到该点为止已解析的整数值。 */
/* 说明:字符串123abc中,从左向右解析,遇到2的时候解析就停止了 */
console.log(parseInt('123abc', 2)); /* 等价于parseInt('1' , 2) ==> 1*/
console.log(parseInt('123abc', 3)); /* 等价于parseInt('12', 3) ==> 5*/
/* 如果没有指定转换的进制那么就默认以10进制的方式来处理 */
console.log(parseInt('123abc')); /* 123 */
/* 如果第一个参数不是字符串那么会默认调用对应的 toString来转换 */
console.log(parseInt(101, 2)); /* 5 */
console.log(parseInt([7, 2, 3]));
/* 分析代码的处理过程 */
/* (1) [7,2,3]非字符串会默认转换为字符串,[7,2,3].toString() => "7,2,3" */
/* (2) parseInt("7,2,3",10) */
/* (3) parseInt("7",10) */
/* (4) 7 */
JavaScript 语言中的数据表示都是浮点型的,我们在进行转换的时候可能还需要考虑到小数的问题,而且 JavaScript 也是一门典型的0.1 + 0.2 !== 0.3
的语言,下面简单通过代码来展示下这些问题。
console.log((6.625).toString(2)) /* 110.101 */
/*110.101 =1 x 2^(2) +1 x 2^(1) +0 x 2^(0) +1 x 2^(-1) +0 x 2^(-2) +1 x 2^(-3)*/
/* =4 +2 +0 +0.5 +0 +0.125 */
/* =6.625 */
/* 浮点数字符串转换为二进制数据 */
console.log(parseInt("101.011", 2)) /* 5 说明:小数点后面的数会被截断*/
/* 浮点数 */
let num = 17.235; /* 整数部分:17 小数部分:0.235 */
console.log(num.toString(2));
/* 结果:10001.0011110000101000111101011100001010001111010111 */
/* 二进制表示 */
console.log((0.1).toString(2));
/* 结果:0.0001100110011001100110011001100110011001100110011001101 */
console.log((0.2).toString(2));
/* 结果:0.001100110011001100110011001100110011001100110011001101 */
/* 执行按位相加操作 */
console.log(0.1 + 0.2) /* 0.30000000000000004 */
console.log(0.1 + 0.2 === 0.3) /* false */