前端开发系列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 */ 
相关推荐
编程猪猪侠26 分钟前
Tailwind CSS 自定义工具类与主题配置指南
前端·css
qhd吴飞30 分钟前
mybatis 差异更新法
java·前端·mybatis
YGY Webgis糕手之路1 小时前
OpenLayers 快速入门(九)Extent 介绍
前端·经验分享·笔记·vue·web
患得患失9491 小时前
【前端】【vueDevTools】使用 vueDevTools 插件并修改默认打开编辑器
前端·编辑器
ReturnTrue8681 小时前
Vue路由状态持久化方案,优雅实现记住表单历史搜索记录!
前端·vue.js
UncleKyrie1 小时前
一个浏览器插件帮你查看Figma设计稿代码图片和转码
前端
遂心_1 小时前
深入解析前后端分离中的 /api 设计:从路由到代理的完整指南
前端·javascript·api
你听得到111 小时前
Flutter - 手搓一个日历组件,集成单日选择、日期范围选择、国际化、农历和节气显示
前端·flutter·架构
风清云淡_A1 小时前
【REACT18.x】CRA+TS+ANTD5.X封装自定义的hooks复用业务功能
前端·react.js
@大迁世界1 小时前
第7章 React性能优化核心
前端·javascript·react.js·性能优化·前端框架