【问题标题】:What is the "double tilde" (~~) operator in JavaScript? [duplicate]JavaScript 中的“双波浪号”(~~) 运算符是什么? [复制]
【发布时间】:2011-05-11 23:18:14
【问题描述】:

我在一些代码中看到了这一点,但我不知道它的作用:

var jdn = function(y, m, d) {
  var tmp = (m <= 2 ? -1 : 0);
  return ~~((1461 * (y + 4800 + tmp)) / 4) + 
         ~~((367 * (m - 2 - 12 * tmp)) / 12) - 
         ~~((3 * ((y + 4900 + tmp) / 100)) / 4) + 
         d - 2483620;
};

~~ 运算符是做什么的?

【问题讨论】:

  • 您现在可能已经弄清楚了,但它会返回千年与给定日期之间的天数
  • 当我在 codewars 上看到它时,谷歌搜索了这个,结果发现 google 不支持波浪号。谢谢鸭鸭!
  • 简单来说,它会将 '9' 转换为数字 9。如果您在控制台中执行以下操作,即使使用 IE8,它也必须比 Math.floor() 快: typeof ~~'9'/ /号码
  • 没有 cmets 是一回事,但我最讨厌的是有人将其命名为 jdn。我什至不知道那代表什么。
  • Math.trunc(),而不是 Math.floor()

标签: javascript


【解决方案1】:

~~ 是一个双非按位运算符。

它用作faster substitute for Math.floor() 用于 数字。对于负数,它不会返回与 Math.floor() 相同的结果,因为它只是去掉小数点后的部分(有关示例,请参见其他答案)。

【讨论】:

  • @ghoppe:值得注意的是,它与.floor() 的不同之处在于它实际上只是删除了小数点右侧的任何内容。当用于负数时,这会有所不同。此外,它总是会返回一个数字,并且永远不会给你NaN。如果不能转换成数字,你会得到0
  • @ghoppe:是的,两个not操作实际上比单层方法快。当我在计算机上的 Firefox 中测试它们时,它们的运行时间约为 0.2 微秒,而不是 0.5 微秒。这意味着您需要大量使用它才能引起注意。在像 OP 中这样的功能中,它只是微优化,只会使代码更难遵循。
  • 我在使用这种具有非常大数字的技术时遇到了整数溢出问题(在 base-62 编码期间将来自 Navigation Timing API 的数字除以 62 的结果)。例如,在 Firefox、Chrome 和 IE 中,~~(2419354838.709677) == -1875612458,而 Math.floor(2419354838.709677) == 2419354838。
  • 不要使用~~!在 IE10 中,它比对同一事物执行其他按位运算慢 8 倍!最好使用零右移(>>0),它是最快的,看起来更类似于有符号到无符号的转换(>>>0)。
  • 类似于 Math.trunc(),但不是 Math.floor()
【解决方案2】:

它隐藏了代码的意图。

它是两个单波浪号运算符,因此它执行按位补码(按位不)两次。这些操作相互抵消,因此唯一剩下的效果是在应用第一个运算符之前完成的转换,即将值转换为整数。

有些人将其用作Math.floor 的更快替代方案,但速度差异并没有那么大,而且在大多数情况下,它只是微优化。除非您有一段确实需要优化的代码,否则您应该使用描述其作用的代码,而不是使用非操作的副作用的代码。

2011-08 更新:

随着浏览器中 JavaScript 引擎的优化,运算符和函数的性能发生了变化。在当前的浏览器中,使用~~ 而不是Math.floor 在某些浏览器中会稍微快一些,而在某些浏览器中则根本不快。如果你真的需要额外的性能,你需要为每个浏览器编写不同的优化代码。

见:tilde vs floor

【讨论】:

  • +1 表示“它隐藏了代码的意图”,我浪费了 10 分钟来了解 ~~ 的作用。无论如何,我也不得不承认,我的黑暗面已经很强大了,它已经诱使我在我的新代码中永远使用~~ 代替Math.floor。 :))))
  • 请注意,像 JSPerf 这样的微测试(必须)运行测试代码的次数足够多,以至于动态运行时优化(例如在 V8 中)会发挥作用。该测试表明(如果大量使用) Math.floor() 可以在 Chrome 上与 ~~ 一样快,但并不是说它总是相同的速度。现在很难确定一段代码是否比另一段“更快”(考虑到不同的浏览器和调用场景)。
  • 为什么 Chrome 22 比 Chrome 8 慢这么多??
  • @MattSach:只有在同一台计算机上进行测试,或者有足够多的人对其进行了测试,这些数据才具有可比性。 Chrome 有这么多版本,几乎只有少数人测试过每个版本的代码。
  • 请记住 Math.floor() 的存在是有原因的。不要使用 ~~ 因为它比 Math.floor 快 2 微秒,如果您不了解它可能导致溢出或其他意外结果的位置。
【解决方案3】:
~(5.5)   // => -6
~(-6)    // => 5
~~5.5    // => 5  (same as Math.trunc(5.5) and Math.floor(5.5))
~~(-5.5) // => -5 (same as Math.trunc(-5.5) but NOT the same as Math.floor(-5.5), which would give -6 )

有关详细信息,请参阅:

【讨论】:

  • ~(-5.5) => 4, ~(4) => -5, ~~(-5.5) => -5。因此,不等于Math.floor
  • @zzzzBov,我更新了帖子以澄清~~ 与负数的Math.floor() 不同。
  • Math.floor(-5.5),这将给出 -6。 Bcos Math.floor 将返回小于或等于给定数字的最大整数。 Math.floor(-5.00000001) 也给出 -6。
【解决方案4】:

区别很简单:

加长版

如果您想获得更好的可读性,请使用Math.floor。但是如果你想最小化它,使用波浪号~~

互联网上有很多消息来源说Math.floor 更快,但有时~~。我不建议您考虑速度,因为在运行代码时不会注意到它。也许在测试等中,但没有人可以在这里看到差异。更快的是使用~~ 来获得更快的加载时间。

短版

~~ 更短/占用更少空间。 Math.floor 提高了可读性。有时波浪号更快,有时Math.floor 更快,但并不明显。

【讨论】:

  • 对。它主要是一种风格选择,例如当您想将变量转换为布尔值时,可以在 Boolean(foo)、(foo ? true : false) 或 !!foo 之间进行选择。
  • Math.trunc(),而不是 Math.floor()
猜你喜欢
  • 2011-08-23
  • 2012-02-26
  • 2012-07-31
  • 2011-05-02
  • 2011-05-02
相关资源
最近更新 更多