本文将会列举并说明JavaScript 把一个number(或者numerical的对象)转换成一个整数相关方法。

使用parseInt

parseInt的语法如下:parseInt(string, radix)
参数string的表示要解析的字符串,也可以是一个对象,会自动调用对象的toString函数得到要解析的字符串。

parseInt的第二个参数,可以指定要解析的数字的基数,注意该值介于 2 ~ 36 之间,如果该参数小于 2 或者大于 36,则 parseInt() 将返回 NaN。比如下面的代码,结果为8,这样可以很方便的把其他的进制的数字转换为10进制的数字:

parseInt(10,8) // 结果为8

当参数 radix 的值为 0,或没有设置该参数时,parseInt() 会根据 string 来判断数字的基数。
举例,如果 string 以 "0x" 开头,parseInt() 会把 string 的其余部分解析为十六进制的整数。如果 string 以 0 开头,那么 ECMAScript v3 允许 parseInt() 的一个实现把其后的字符解析为八进制或十六进制的数字。如果 string 以 1 ~ 9 的数字开头,parseInt() 将把它解析为十进制的整数。

注释
1. 只有字符串中的第一个数字会被返回。 什么意思呢,如果输入的字符串是"123abc","123,123",那么结果是123,parseInt方法会自动忽略后面的非数字部分。
2. 输入字符串开头和结尾的空格是允许的。
3. parseFloat 也具备以上两条特征,不过本文不重点讲述。

使用Math.trunc

Math.trunc() 方法会将数字的小数部分去掉,只保留整数部分。比如以下代码:

Math.trunc(13.37)    // 13
Math.trunc(42.84) // 42
Math.trunc(0.123) // 0
Math.trunc(-0.123) // -0
Math.trunc("-1.123") // -1
Math.trunc(NaN) // NaN
Math.trunc("foo") // NaN
Math.trunc() // NaN

当传入的类型不是数字的时候,会自动做瘾式转换。但是如果是一个非numerical的参数的时候,返回NaN。
IE浏览器并不支持这个方法,所以可以考虑polyfill:

Math.trunc || (Math.trunc = function(v){
return v < 0 ? Math.ceil(v) : Math.floor(v); // 使用Math.floor和Math.ceil方法
})
// 或者
if (!Math.trunc) {
Math.trunc = function(v) {
v = +v;
if (!isFinite(v)) return v; return (v - v % 1) || (v < 0 ? -0 : v === 0 ? v : 0); // 返回:
// 0 -> 0
// -0 -> -0
// 0.2 -> 0
// -0.2 -> -0
// 0.7 -> 0
// -0.7 -> -0
// Infinity -> Infinity
// -Infinity -> -Infinity
// NaN -> NaN
// null -> 0
};
}

二进制位运算

对于numerical的对象n,可以通过如下的方式来转换为整数:

  • ~~n 双重位取反(Double bitwise NOT)
  • n | n 位或运算(Bitwise OR)
  • n | 0 和0的位或运算(Bitwise OR with 0)
  • n << 0 位左移运算0位(Bitwise left shift)
  • n >> 0 位右移运算0位(Bitwise right shift)
  • n & n 为与运算(Bitwise AND)
    比如代码如下:
   ~~1.23 // 1
-1.2 | -1.2 // - 1
-1.2 | 0 // - 1
3.4 >> 0 // 3
3.2 << 0 // 3
5.5 & 5.5 // 5
~~"1.2" // 1.2

注意,从上面可以看出,位运算下字符串会自动转换数字。

性能测试

下面这个网址可以测试以上方法测性能情况,其中没有用到Math.trunc方法,用Math.floor方法代替了Math.trunc方法:
https://jsperf.com/rounding-numbers-down

我测试的结果如下,可以发现速度上,parseInt是最慢的,其他方法相对较快:

性能测试

从代码量的角度来说,n | 0 或则 ~~n是字符最少的,写起来应该也是最方便的, 但是可读性会变差。

另外自己写代码测试了下Math.trunc和Math.floor的速度,比较结果如下:

    console.time('Math.trunc');
for(var i = 0;i < 1000000000;i ++){
Math.trunc(3.3);
}
console.timeEnd('Math.trunc'); console.time('Math.floor');
for(var i = 0;i < 1000000000;i ++){
Math.floor(3.3);
}
console.timeEnd('Math.floor');
// Math.trunc: 8658.009033203125ms
// Math.floor: 7916.7890625ms

位操作转换整数的原理

参考Mozilla上面对于位操作的说明,点击下面链接:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators
有这样一段话:

Bitwise operators treat their operands as a sequence of 32 bits (zeroes and ones), rather than as decimal, hexadecimal, or octal [numbers]

JavaScript中,数字存储是双进度64位浮点数。但是位操作却会把要操作的运算元当做32位带符号的整数。因此进行位操作时,会自动把数字先转换为整数。对数字n做前面提到的位运算,相当于n & 0xFFFFFFFF

位运算优缺点

用位操作进行整数转换的优点,大概包括如下:

  • 性能更快
  • 代码字符可以更少(比如 n | 0或者~~n)

用位操作进行整数转换的缺点,大概包括如下:

  • 代码不易懂
  • 可能不能通过jsLint
  • 只支持32位以内的数据,超过范围就会得出错误的结果。

对于“只支持32位以内的数据,超过范围就会得出错误的结果”这一点,因为位运算会把运算元当做32位带符号的整数,其范围是-2,147,483,648 到 2147483647 (0x7FFFFFFFF),超过范围就不奏效了。比如如下代码

~~2147483648.1//-2147483648

由于2147483648.1超过了范围,其结果变成了-2147483648,而不是2147483648。下面列出安全和不安排的转换的更多示例:

 // Safe
(2147483647.5918 & 0xFFFFFFFF) === 2147483647
(2147483647 & 0xFFFFFFFF) === 2147483647
(200.59082098 & 0xFFFFFFFF) === 200
(0X7FFFFFFF & 0xFFFFFFFF) === 0X7FFFFFFF // Unsafe
(2147483648 & 0xFFFFFFFF) === -2147483648
(-2147483649 & 0xFFFFFFFF) === 2147483647
(0x80000000 & 0xFFFFFFFF) === -2147483648
(3000000000.5 & 0xFFFFFFFF) === -1294967296

为了能够提高性能,又保证超过范围的时候安全可靠,可以考虑下面的polyfill:

function trunc(n) {
if (n > -0x80000000 && n < 0x80000000) {
return n & 0xFFFFFFFF; //此处可以用 ~~n,n | 0等等
}
return Math.trunc(n);
}

Math.round 扩展

同样可以用位操作实现Math.round的功能,比如:

参考文档

https://jsperf.com/rounding-numbers-down
https://stackoverflow.com/questions/131406/what-is-the-best-method-to-convert-floating-point-to-an-integer-in-javascript
https://j11y.io/javascript/double-bitwise-not/
https://stackoverflow.com/questions/7487977/using-bitwise-or-0-to-floor-a-number
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators
https://jsperf.com/math-round-vs-hack/25

欢迎关注公众号“ITman彪叔”。彪叔,拥有10多年开发经验,现任公司系统架构师、技术总监、技术培训师、职业规划师。熟悉Java、JavaScript。在计算机图形学、WebGL、前端可视化方面有深入研究。对程序员思维能力训练和培训、程序员职业规划和程序员理财投资有浓厚兴趣。

ITman彪叔公众号

JavaScript 转换数字为整数的方法的更多相关文章

  1. Javascript中将数字转换为中文的方法

    //js实现将数字1234转化为汉字字符串(一千二百三十四)(或大写汉字壹仟贰佰叁拾肆): /*阿拉伯数字转中文数字 中文数字的特点: 每个计数数字都跟着一个权位,权位有:十.百.千.万.亿. 以“万 ...

  2. JavaScript转换与解析JSON的方法

    在JavaScript中将JSON的字符串解析成JSON数据格式,一般有两种方式: 一种为使用eval()函数. 使用Function对象来进行返回解析. 使用eval函数来解析,jquery的eac ...

  3. JavaScript进阶(四)js字符串转换成数字的三种方法

    js字符串转换成数字的三种方法 在js读取文本框或者其它表单数据的时候获得的值是字符串类型的,例如两个文本框a和b,如果获得a的value值为11,b的value值为9 ,那么a.value要小于b. ...

  4. JavaScript字符串转数字的5种方法及其陷阱

    摘要 :JavaScript 是一个神奇的语言,字符串转数字有 5 种方法,各有各的坑法! String 转换为 Number 有很多种方式,我可以想到的有 5 种! parseInt(num); / ...

  5. javascript 中关于对象转换数字值的一些特点

    下面是摘至<Javascript 高级程序设计第三版>里的一段话 是关于对象转换数字值的一些规则 "在应用于对象时,先调用对象的valueOf()方法以取得一个可供操作的值.然后 ...

  6. js字符串转换成数字与数字转换成字符串的实现方法

    转载:点击查看地址 js字符串转换成数字 将字符串转换成数字,得用到parseInt函数.parseInt(string) : 函数从string的开始解析,返回一个整数. 举例:parseInt(' ...

  7. js字符串转换为数字的三种方法。(转换函数)(强制类型转换)(利用js变量弱类型转换)

    js字符串转换为数字的三种方法.(转换函数)(强制类型转换)(利用js变量弱类型转换) 一.总结 js字符串转换为数字的三种方法(parseInt("1234blue"))(Num ...

  8. js 将数字转换成人民币大写的方法

    //将数字转换成人民币大写的方法 var digitUppercase = function (n) { var fraction = ['角', '分']; var digit = [ '零', ' ...

  9. JavaScript中判断为整数的多种方式

    之前记录过JavaScript中判断为数字类型的多种方式,这篇看看如何判断为整数类型(Integer). JavaScript中不区分整数和浮点数,所有数字内部都采用64位浮点格式表示,和Java的d ...

随机推荐

  1. WordPress自定义菜单和修改去除多余的css

    这里主要是用于模板制作的,一般前端已经写好了,我们只要将前端的内容套用WordPress后台就可以了. 所以我们在模板制作过程中,需要自定义WordPress菜单. 在functions.php文件中 ...

  2. 《精通并发与Netty》学习笔记(13 - 解决TCP粘包拆包(一)概念及实例演示)

    一.粘包/拆包概念 TCP是一个“流”协议,所谓流,就是没有界限的一长串二进制数据.TCP作为传输层协议并不不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行数据包的划分,所以在业务上认 ...

  3. C/C++编程

    基本的数据类型: 整型 浮点型(单精度.双精度) 在c语言中,所有的变量声明必须在任何执行语句之前(对当前域来说), 否则编译的时候会出现变量是未声明的标识符的错误. main 入口参数:argc 和 ...

  4. NDK学习笔记-多线程与生产消费模式

    在做NDK开发的时候,很多情况下都是需要使用多线程的,一方面是提高程序运行效率,另一方面就是防止主线程阻塞 C的多线程 在C语言里,可以通过对于POSIX标准的运用,使得C语言执行多线程 提高程序的执 ...

  5. MyBatis使用技巧、总结、注意事项

    目录 1.mybatis的官方文档地址 2.其他技巧: 2.1 如何在代码中拼接 like %% 2.2 数据库比较时日期的错误操作 2.2.1 异常情况: 2.2.2 为什么会在后面指定jdbcTy ...

  6. go语言简单介绍,增强了解

    1. Go语言没有类和继承的概念,所以它和 Java 或 C++ 看起来并不相同.但是它通过接口(interface)的概念来实现多态性.Go语言有一个清晰易懂的轻量级类型系统,在类型之间也没有层级之 ...

  7. 如何使用 Issue 管理软件项目?

    软件开发(尤其是商业软件)离不开项目管理,Issue 是最通用的管理工具之一.

  8. nginx 开启gzip压缩

    Nginx开启Gzip压缩功能, 可以使网站的css.js .xml.html 文件在传输时进行压缩,提高访问速度,!  Web网站上的图片,视频等其它多媒体文件以及大文件,因为压缩效果不好,所以对于 ...

  9. pytorch安装问题

    目录 1.版本 2.pytorch调试中出现的Module 'torch' has no 'zero' member如何解决 3.No module named 'numpy.core._multia ...

  10. [转帖]IBM 开源 POWER 指令集架构

    IBM 开源 POWER 指令集架构 https://www.solidot.org/story?sid=61791 新闻越短 事情越严重 IBM 破釜沉舟 OpenPOWER 联盟国产化披荆斩棘? ...