将布尔结果转换为数字/整数
我有一个存储 false
或 true
的变量,但我分别需要 0
或 1
。我该怎么做?
I have a variable that stores false
or true
, but I need 0
or 1
instead, respectively. How can I do this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(21)
使用 一元
+
运算符,将其操作数转换为数字。当然,请注意,您仍然应该在服务器端清理数据,因为用户可以将任何数据发送到您的服务器,无论客户端代码说什么。
Use the unary
+
operator, which converts its operand into a number.Note, of course, that you should still sanitise the data on the server side, because a user can send any data to your sever, no matter what the client-side code says.
Javascript 有一个三元运算符,您可以使用:
Javascript has a ternary operator you could use:
恕我直言,最好的解决方案是:
这在 asm.js 中用于强制整数类型。
Imho the best solution is:
This is used in asm.js to force integer type.
我更喜欢使用数字函数。它接受一个对象并将其转换为数字。
示例:
您可以在 jsFiddle 中测试它。
I prefer to use the Number function. It takes an object and converts it to a number.
Example:
You can test it in a jsFiddle.
执行此操作的键入方法是:
The typed way to do this would be:
我创建了所有建议答案的 JSperf 比较。
TL;DR - 所有当前浏览器的最佳选择是:
.
更新:
现在看来它们都非常相同,除了
Number()
函数是最慢的,而最好的是val === true ? 1:0;
。I created a JSperf comparison of all suggested answers.
TL;DR - the best option for all current browsers is:
.
Update:
It seems like these days they are all pretty identical, except that the
Number()
function is the slowest, while the best beingval === true ? 1 : 0;
.我今天才发现这条捷径。
~~(true)
~~(false)
人们比我能解释的聪明得多:
http: //james.padolsey.com/javascript/double-bitwise-not/
I just came across this shortcut today.
~~(true)
~~(false)
People much smarter than I can explain:
http://james.padolsey.com/javascript/double-bitwise-not/
TL;DR:避免
Number
构造函数和+bool
;默认情况下使用简单的if
;求助于bool | 0
,1 * bool
如果您的项目中的基准测试通过这种方式表现得更好。这是一个相当老的问题,并且有很多有效的答案。我注意到,这里的所有基准测试都是无关紧要的 - 没有考虑到 分支 预测。另外,如今,JS 引擎不再简单地解释代码,它们 JIT 将其编译为本机机器代码并在执行之前对其进行优化。这意味着,除了分支预测之外,编译器甚至可以用最终值替换表达式。
现在,这两个因素如何影响布尔到整数转换的性能?让我们来看看吧!在我们进行基准测试之前,了解我们的基准测试内容很重要。对于转换,我们使用以下七种转换方法:
Number(bool)
bool ? 1 : 0
+
:+bool
bool | 0
bool & 1
~~bool
bool * 1
“转换”表示将
false
转换为0
和true
到1
1。每个转换方法运行 100000 次,测量操作/毫秒。在下表中,转换方法将根据其结果进行相应分组。结果后面的百分比表示在同一浏览器中此方法与最快方法相比有多慢。如果没有百分比,则该方法要么是最快的,要么差异可以忽略不计(<0.01%)。基准测试在 Macbook Pro 16 英寸机器上运行,配备 Apple M1 Pro 10 核 CPU 和 16GB RAM。浏览器为 Chrome 102、Firefox 101 和 Safari 15.5。第一个 基准 转换常量
true
:Number(bool)
+bool
bool | 0
~~布尔
布尔 * 1
有趣! V8 显示了一些巨大的数字,所有这些数字都大致相同! Spidermonkey 并没有真正发光,但我们可以看到按位和乘法技巧是第一位的,然后是三元运算技巧。最后,Webkit 的
Number
与 V8 的类似,其他方法落后,但彼此接近。有哪些要点?浏览器大多设法用简单的值1
替换我们的转换。这种优化将发生在我们可以在心里将布尔值替换为常量值的地方。Number
构造函数是一个有趣的异常 - 它在 Firefox 中严重落后(慢 91%!),而在 Safari 中它是最快的!上述情况不是我们在实际项目中遇到的情况。因此,让我们更改变量:bool 现在是 Math.random()
Math.random()
Math.random()
0.5。这产生
true
的概率为 50%,false
的概率为 50%。我们的结果会改变吗?让我们运行这个基准测试来看看。数字(bool)
bool ? 1:0
+bool
bool | 0
~~bool
bool * 1
现在结果更加一致。我们在各个浏览器中看到三元 if、按位和乘法方法的数字相似,并且
Number
构造函数在 Firefox 上的表现再次最差。三进制落后了,因为它会产生分支。总体而言,Safari 似乎是我们表现最好的,每种方法都能快速产生结果!现在让我们看看分支预测如何通过以下基准影响我们的结果,其中我们将布尔变量更改为<代码>Math.random() < 0.01,这意味着 1%
true
,99%false
。Number(bool)
bool ? 1:0
+bool
bool | 0
~~bool
bool * 1
意外?预期的?我想说后者,因为在这种情况下,分支预测在几乎所有情况下都是成功的,因为三元 if 和按位 hack 之间的差异较小。其他的结果都是一样的,这里就不多说了。我仍然会指出
Number
在 Firefox 中的可怕性能 - 为什么?这一努力让我们回到了最初的问题:如何在 Javascript 中将 bool 转换为 int?以下是我的建议:
if (bool)
而不是那个丑陋的三元组!我希望 Javascript 具有 Rust 或 Python 有...if
会导致性能不佳 - 如果是这种情况,请随时进入 无分支 编程!但不要在那个兔子洞里走得太深,相信我,没有人会从-1 * (a < b) + 1 * (a > b)
这样的东西中受益。还有一些细节:
Number(bool)
。虽然 Chromium 平台(Chrome + Edge)在全球拥有约 68% 的市场份额,Safari 为 19%,Firefox 仅为 3.6%,但还有足够多的其他快速执行方法,不会完全牺牲一定比例的用户。 Firefox 拥有 7% 的桌面市场份额,相当于 1.73 亿用户。+bool
的表现与 Firefox 中的Number
的表现类似,也许也考虑到这一点 - 按位黑客和乘法在所有浏览器中给出了一致的性能结果情况。bool | 0
最有机会被其他开发者熟悉。编辑:以前的基准测试工具提供了模糊的结果,没有测量单位。我已经改变了它,并且还添加了 Safari 的基准,这影响了结论。
TL;DR: Avoid
Number
constructor and+bool
; use a simpleif
by default; resort tobool | 0
,1 * bool
if benchmarks in your project do better this way.This is quite an old question, and there exist many valid answers. Something I've noticed is that all benchmarks here are irrelevant - none take into account branch prediction. Also, nowadays, JS engines don't simply interpret the code, they JIT compile it to native machine code and optimize it prior to execution. This means that, besides branch prediction, the compiler can even substitute expressions with their final value.
Now, how do these 2 factors affect the performance of, well, boolean to integer conversion? Let's find out! Before we get into the benchmarks, it is important to know what we benchmark. For the conversion, we're using the following seven conversion methods:
Number(bool)
bool ? 1 : 0
+
:+bool
bool | 0
bool & 1
~~bool
bool * 1
"Conversion" means converting
false
to0
andtrue
to1
1. Each conversion method is ran 100000 times, measuring operations/millisecond. In the following tables, conversion methods will be grouped to their results accordingly. The percentage after the result represents how slow this method is compared to the fastest, in the same browser. If there is no percentage, the method is either the fastest or the difference is negligible (<0.01%). Benchmarks are run on a Macbook Pro 16-inch machine, with the Apple M1 Pro 10-core CPU and 16GB of RAM. Browsers are Chrome 102, Firefox 101 and Safari 15.5.The first benchmark converts the constant
true
:Number(bool)
bool ? 1 : 0
+bool
bool | 0
bool & 1
~~bool
bool * 1
Interesting! V8 shows some huge numbers, all of them approximately the same! Spidermonkey doesn't really shine, but we can see that the bitwise and multiplication tricks come first, and the ternary if second. Finally, Webkit's
Number
does similarly to V8's and the other methods fall behind, but are all close to each other. What are the takeaways? Browsers mostly manage to replace our conversions with simply the value1
. This optimization will take place where we can mentally replace the boolean to a constant value. TheNumber
constructor is an intriguing anomaly - it severly falls behind in Firefox (91% slower!), while in Safari it is the fastest!That above isn't a situation we'll ever encounter in real projects. So let's change our variables: the bool is now
Math.random() < 0.5
. This yields a 50% chance oftrue
, 50% offalse
. Do our results change? Let's run this benchmark to see.Number(bool)
bool ? 1 : 0
+bool
bool | 0
bool & 1
~~bool
bool * 1
The results are more consistent now. We see similar numbers for ternary if, bitwise, and multiplication methods across browsers, and the
Number
constructor again performs the worst on Firefox. Ternary falls behind, as it generates branches. Safari seems to be our top performer overall, each method yielding blazing fast results!Let's see now how branch prediction affects our results with the following benchmark, where we change our boolean variable to
Math.random() < 0.01
, which means 1%true
, 99%false
.Number(bool)
bool ? 1 : 0
+bool
bool | 0
bool & 1
~~bool
bool * 1
Unexpected? Expected? I'd say the latter, because in this case branch prediction was successful in almost all cases, given the smaller difference between the ternary if and bitwise hacks. All other results are the same, not much else to say here. I'll still point out the horrific performance of
Number
in Firefox - why?This endeavour brings us back to the original question: how to convert bool to int in Javascript? Here are my suggestions:
if (bool)
instead of that ugly ternary! I wish Javascript had what Rust or Python have...if
causes bad performance - if that's the case, feel free to get into branchless programming! But don't go too deep in that rabbit hole, nobody will benefit from things like-1 * (a < b) + 1 * (a > b)
, believe me.And some specifics:
Number(bool)
. While it is true that the Chromium platform (Chrome + Edge) has about 68% market share globally, Safari 19% and Firefox a mere 3.6%, there are enough other fast-performing methods that won't fully sacrifice a percentage of your users. Firefox has 7% desktop market share, which amounts to a sizable number of 173 million users.+bool
performed similarly bad toNumber
in Firefox, maybe take this in consideration, too - bitwise hacks and multiplication give consistently performant results across all browsers, in all situations.bool | 0
has the best chance to be familiar to other developers.EDIT: The previous benchmarking tool provided vague results, without an unit of measure. I've changed it, and also added benchmarks for Safari, which have influenced the conclusions.
当 JavaScript 需要数字值但收到布尔值时,它会将该布尔值转换为数字:true 和 false 分别转换为 1 和 0。所以你可以利用这一点;
进一步阅读《Javascript 权威指南》的类型转换第 3.8 章。
When JavaScript is expecting a number value but receives a boolean instead it converts that boolean into a number: true and false convert into 1 and 0 respectively. So you can take advantage of this;
Further reading Type Conversions Chapter 3.8 of The Definitive Guide to Javascript.
我只是在编写的一些代码中处理这个问题。我的解决方案是使用按位与。
处理持续问题的更快方法是创建一个函数。它更容易被其他人阅读,在维护阶段更好地理解,并且消除了写错东西的可能性。
编辑 - 2014 年 9 月 10 日
由于某种原因,在 Chrome 中使用三元运算符与相同运算符进行转换的速度并不快。没有任何意义为什么它更快,但我认为这是某种低级优化,在整个过程中的某个地方有意义。
自己测试一下:http://jsperf.com/boolean-int-conversion/2
在 FireFox 和 Internet Explorer 中,使用我发布的版本通常速度更快。
编辑 - 2017 年 7 月 14 日
好吧,我不会告诉您应该或不应该使用哪一个。每个奇怪的浏览器在使用每种方法执行操作的速度上都在上下波动。 Chrome 曾经一度拥有按位 & 功能。版本比其他版本做得更好,但随后突然变得更糟。我不知道他们在做什么,所以我就把它留给在乎的人。很少有任何理由去关心这样的操作完成的速度有多快。即使在移动设备上,这也是一个无操作。
另外,这里有一个更新的方法,用于添加不能被覆盖的“toInt”原型。
I was just dealing with this issue in some code I was writing. My solution was to use a bitwise and.
A quicker way to deal with a constant problem would be to create a function. It's more readable by other people, better for understanding at the maintenance stage, and gets rid of the potential for writing something wrong.
Edit - September 10th, 2014
No conversion using a ternary operator with the identical to operator is faster in Chrome for some reason. Makes no sense as to why it's faster, but I suppose it's some sort of low level optimization that makes sense somewhere along the way.
Test for yourself: http://jsperf.com/boolean-int-conversion/2
In FireFox and Internet Explorer, using the version I posted is faster generally.
Edit - July 14th, 2017
Okay, I'm not going to tell you which one you should or shouldn't use. Every freaking browser has been going up and down in how fast they can do the operation with each method. Chrome at one point actually had the bitwise & version doing better than the others, but then it suddenly was much worse. I don't know what they're doing, so I'm just going to leave it at who cares. There's rarely any reason to care about how fast an operation like this is done. Even on mobile it's a nothing operation.
Also, here's a newer method for adding a 'toInt' prototype that cannot be overwritten.
一元
+
运算符会处理这个问题:在存储它之前,您自然会希望在服务器上对其进行健全性检查,因此无论如何,这可能是一个更明智的地方。
The unary
+
operator will take care of this:You'll naturally want to sanity-check this on the server before storing it, so that might be a more sensible place to do this anyway, though.
您还可以添加 0、使用移位运算符或异或:
它们的速度与其他答案相似。
You can also add 0, use shift operators or xor:
These have similar speeds as those from the others answers.
在我的上下文中,React Native 中我从布尔值获取不透明度值,最简单的方法是:使用一元 + 运算符。
这会将布尔值转换为数字;
In my context, React Native where I am getting opacity value from boolean, the easiest way: Use unary + operator.
This converts the boolean into number;
+!!
允许您将其应用于变量,即使它是未定义
:+!!
allows you to apply this on a variable even when it'sundefined
:您可以通过简单地扩展布尔原型来做到这一点
理解那里发生的事情并不是太容易,因此替代版本将
完成,您可以做类似的事情
当我使用布尔值来存储条件时我经常将它们转换为位字段在这种情况下,我最终使用原型函数的扩展版本
,您可以使用
它生成 4 作为其输出。
You could do this by simply extending the boolean prototype
It is not too easy to understand what is going on there so an alternate version would be
having done which you can do stuff like
When I use booleans to store conditions I often convert them to bitfields in which case I end up using an extended version of the prototype function
with which you can do
which produces 4 as its output.
尝试
try
我已经测试了所有这些示例,我做了一个基准测试,最后我建议您选择较短的一个,它不会影响性能。
结果
I have tested all of this examples, I did a benchmark, and finally I recommend you choose the shorter one, it doesn't affect in performance.
Result
将建议的方法放在 jsben.ch 中:
https://jsben.ch/d33N1。
每次测试都会给出不同的结果,但每次测试中最好的方法是按位运算:
0|bool
/bool|0
/1&bool
/1&bool
/~~bool
。Put suggested methods in jsben.ch:
https://jsben.ch/d33N1.
It gives different results every test, but the best methods in every test are bitwise operations:
0|bool
/bool|0
/1&bool
/1&bool
/~~bool
.所有浏览器都支持,支持输入为布尔值或布尔值的字符串表示形式
使用 Chrome 控制台检查它,它可以工作
supported in all browsers, supports input as boolean or as a string representation of a boolean
Use Chrome console to check it, it works
我知道我这样做有点晚了,但是您可以使用所谓的模。取模运算符在 JS 中用百分号 (%) 字符表示。它的目标是给出剩余部分。因此,如果我们将数字除以
2%
,它会查找任何能被 2 整除的东西。如果不是,那么余数为 1,情况总是如此,所以你知道这很奇怪。在这种情况下,您要做的就是首先为integer
提供您想要的任何数字,在这种情况下,您需要0
或1
>。如果插入
1
,它将打印false
,而0
将打印true
。我希望这有帮助。
I know I'm a little late to do this, but you can use what's called a modulo. The modulo operator is represented by the percent (%) character in JS. Its goal is to give the remainder. So if we were to divide the number by
2%
, it would look for anything divisible than 2. If it isn't, then you have a remainder of 1, which will always be the case, so you know it's an odd. In this case, what you're going to do is first give theinteger
any number you desire, in which case you want a0
or1
.If you insert
1
it will printfalse
while0
will printtrue
.I hope this helps.