文档章节

快速的取整方法(~~)

hanbb
 hanbb
发布于 2017/08/01 09:58
字数 1237
阅读 48
收藏 0

最近看一篇js装逼小技巧————双波浪号的妙用(将内容转化为数字,或者小数取整),但是本身我的JavaScript水平比较低对其底层操作和其使用范围不甚了解;通过翻阅资料现进行简单的整理。 ###装逼技巧地址&截图### 地址

图片

###~~的本质### ~~被称为“双按位非”操作符。你通常可以使用它作为代替Math.trunc()的更快的方法。 一个按位非操作符~首先将输入input截取为32位,然后将其转换为-(input+1)。因此双按位非操作符将输入转换为-(-(input + 1)+1),使其成为一个趋向于0取整的好工具。对于数字的输入,它很像Math.trunc()。失败时返回0,这可能在解决Math.trunc()转换错误返回NaN时是一个很好的替代。

// 单个 ~
console.log(~1337)// -1338
// 数字输入
console.log(~~47.11)  // -> 47
console.`log`(~~1.9999) // -> 1
console.log(~~3)  // -> 3

然而, 尽管~~可能有更好的性能,有经验的程序员通常坚持使用Math.trunc()。要明白为什么,这里有一个关于此操作符的分析。 ###适用的情况### 当CPU资源很珍贵时

~~可能在各平台上都比Math.trunc()快,但是你应该在你所关心的所有平台上测试这种猜想。同样,你通常需要执行数百万这样的操作来看看在运行时有没有明显的影响。

当不需要关心代码清晰度时

如果你想迷惑其他人,或者想在minifier/uglifier时取得更大功效,这是一种相对廉价的方式。 ###禁用的情况### 当你的代码需要维护时

代码可读性始终是最重要的。无论你工作在一个团队,或是贡献给开源仓库,或是单飞。

当你忘记~~永远趋向于0时

新手程序员或许更关注~~的聪明之处,却忘记了“只去掉小数部分”的意义。这在将浮点数转换为数组索引或关联有序的值时很容易导致差一错误 ,这时明显需要一个不同的取整方法。 (代码可读性不高往往会导致此问题)

打个比方,如果你想得到离一个数“最近的整数”,你应该用Math.round()而不是~~,但是由于程序员的惰性和每次使用需要敲10个键的事实,人类的手指往往会战胜冷冷的逻辑,导致错误的结果。

相比之下,Math.xyz()(举例)函数的名字清楚的传达了它们的作用,减少了可能出现的意外的错误。

当处理大数时

因为~首先将数组转换为32位,~~的结果伪值在 ±2.15*10^12左右。如果你没有明确的检查输入值的范围,当转换的值最终与原始值有很大差距时,用户就可能触发未知的行为:

a = 2147483647.123  // 比32位最大正数,再多一点
console.log(~~a)// ->  2147483647 (ok)
a += 10000  // ->  2147493647.123 (ok)
console.log(~~a)// -> -2147483648 (huh?)

一个特别容易中招的地方是在处理Unix时间戳时(从1970年1月1日 00:00:00 UTC开始以秒测量)。一个快速获取的方法:

epoch_int = ~~(+new Date() / 1000) // Date() 以毫秒计量,所以我们缩小它 然而,当处理2038年1月19日 03:14:07 UTC 之后的时间戳时(有时称为Y2038 limit), 可怕的事情发生了:

// 2040年1月1日 00:00:00.123 UTC的时间戳
epoch = +new Date('2040-01-01') / 1000 + 0.123  // ->  2208988800.123
// 回到未来!
epoch_int = ~~epoch // -> -2085978496
console.log(new Date(epoch_int * 1000)) // ->  Wed Nov 25 1903 17:31:44 UTC

// 这很搞笑,让我们来取得正确结论

epoch_flr = Math.floor(epoch)   // ->  2208988800
console.log(new Date(epoch_flr * 1000)) // ->  Sun Jan 01 2040 00:00:00 UTC

当原始输入的数据类型不确定时

因为~~可以将任何非数字类型转换为0:

console.log(~~[])   // -> 0
console.log(~~NaN)  // -> 0
console.log(~~null) // -> 0

一些程序员将其看作适当输入验证的替代品。然而,这将导致奇怪的逻辑问题,因此你不能辨别违法输入还是真正的0。因此这并不推荐。 当很多人认为~~X == Math.floor(X)时

很多人由于很多原因错误的把”双按位非”等同于Math.floor()。如果你不能准确地使用它,最终你很有可能会滥用它。

另一些人很细心的注意正数使用Math.floor()而负数使用Math.ceil(),但这又强制你在处理它的时候需要停下来想一想你处理的数是什么值。这又违背了使用~~快捷无陷阱的目的。

###结论###

  1. 谨慎使用。
  2. 在应用前检查值。
  3. 仔细记录被转化值的相关假设。
  4. 审查代码至少处理:
  • 逻辑错误,不合法的输入作为合法的0传入其他代码模块
  • 输入转换后范围错误
  • 错误的舍入方向导致差一错误

© 著作权归作者所有

hanbb
粉丝 0
博文 7
码字总数 2108
作品 0
私信 提问
十进制小数的二进制,八进制,十六进制转换方法

十进制小数的二进制,八进制,十六进制转换方法 十进制小数转换为二进制小数 方法:“乘2取整” 对十进制小数乘2得到的整数部分和小数部分,整数部分既是相应的二进制数码,再用2乘小数部分(之...

壶漏子
2015/11/25
467
0
【转载】C#使用Math.Floor方法来向下取整

在C#的数值运算中,有时候需要对计算结果舍去小数位保留整数位向下取整即可,此时就可使用内置方法Math.Floor来实现向下取整操作,Math.Floor方法将舍去小数部分,保留整数。Math.Floor方法有...

江湖逍遥
06/09
0
0
JAVA之Math类的数学运算应用详解

Math类中定义了许多方法,这些方法都被定义为static形式,通过Math类可以在主函数中直接调用 调用方法: Math.方法; Math类中还定义了一些数学常量如:PI,E; 调用方法: Math.PI;(PI表示π...

vshcxl
2016/08/10
232
0
Java中数值计算

一、Math类的用法: Math类中提供了三个与取整有关的方法:ceil、floor、round。这些方法的作用与它们的英文名称的含义相对应。 ceil:英文意义是天花板,该方法就表示向上取整,所以,Math.cei...

SRain215
2016/11/23
6
0
javascript学习之对象应用

javascript中的对象有String对象、Math对象、Array对象、Date对象等等。 每个对象都有自己的相应的属性和方法。 比如String对象就有属性length,可以知道字符串的长度。Math对象有属性PI,就...

桃子红了呐
2017/05/30
0
0

没有更多内容

加载失败,请刷新页面

加载更多

lua web快速开发指南(7) - 高效的接口调用 - httpc库

httpc库基于cf框架都内部实现的socket编写的http client库. httpc库内置SSL支持, 在不使用代理的情况下就可以请求第三方接口. httpc支持header、args、body、timeout请求设置, 完美支持各种h...

水果糖的小铺子
57分钟前
3
0
通过四道常问面试题,带你了解什么是数据库分库分表

编者语:为了避免被误解为:「手里有把锤子,看什么都是钉子!」,说明一下不是什么业务都适合分布式数据库,更不是用了分布式数据库性能就一定能得到扩展。 其次:本文为纯干货,建议先转发...

老道士
今天
5
0
springmvc 整体流程

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR......

architect刘源源
今天
3
0
磁盘管理

先来看两个查看的命令 查看磁盘使用情况df 用法:df, df -h, df -m, df -k 查看目录或文件大小 用法:du -sh, du -sm, du -s(默认以k为单位) 新加一块盘如何操作 步骤:分区(可选)--> 格...

wzb88
今天
3
0
在 Linux 下确认 NTP 是否同步的方法

NTP 意即网络时间协议Network Time Protocol,它通过网络同步计算机系统之间的时钟。NTP 服务器可以使组织中的所有服务器保持同步,以准确时间执行基于时间的作业。NTP 客户端会将其时钟与 ...

Linux就该这么学
今天
11
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部