前端开发系列122-进阶篇之Floating point addition

本文简单说明 JavaScript 中常见的进制转换函数以及浮点数计算的注意点。

如何把任意进制的数据转换为十进制?

假设我们有二进制数据110,如果要把该数据转换为十进制数据可以参考下面的处理过程。

ini 复制代码
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

javascript 复制代码
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函数在具体使用的时候有一些注意点,下面通过代码来简单展示这些注意点。

javascript 复制代码
/* 问题: 为什么得到的结果为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的语言,下面简单通过代码来展示下这些问题。

javascript 复制代码
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 */ 
相关推荐
轻口味32 分钟前
命名空间与模块化概述
开发语言·前端·javascript
前端小小王1 小时前
React Hooks
前端·javascript·react.js
迷途小码农零零发1 小时前
react中使用ResizeObserver来观察元素的size变化
前端·javascript·react.js
娃哈哈哈哈呀2 小时前
vue中的css深度选择器v-deep 配合!important
前端·css·vue.js
旭东怪2 小时前
EasyPoi 使用$fe:模板语法生成Word动态行
java·前端·word
ekskef_sef4 小时前
32岁前端干了8年,是继续做前端开发,还是转其它工作
前端
sunshine6414 小时前
【CSS】实现tag选中对钩样式
前端·css·css3
真滴book理喻4 小时前
Vue(四)
前端·javascript·vue.js
蜜獾云4 小时前
npm淘宝镜像
前端·npm·node.js