将布尔结果转换为数字/整数

我有一个存储falsetrue的变量,但我需要分别存储01。我该怎么做呢?

343943 次浏览

使用一元+运算符,它将其操作数转换为数字。

+ true; // 1
+ false; // 0

当然,请注意,您仍然应该在服务器端清除数据,因为用户可以将任何数据发送到您的服务器,而不管客户端代码说了什么。

一元+操作符将处理这些:

var test = true;
// +test === 1
test = false;
// +test === 0

您自然希望在存储它之前在服务器上检查它,因此在服务器上执行此操作可能是一个更明智的地方。

Javascript有一个三元操作符,你可以使用:

var i = result ? 1 : 0;

我今天偶然发现了这条近路。

~ ~(真正的)

~ ~(假)

比我聪明得多的人可以解释:

http://james.padolsey.com/javascript/double-bitwise-not/

我只是在我写的一些代码中处理这个问题。我的解决方案是使用一个位和。

var j = bool & 1;

处理常量问题的一个更快的方法是创建一个函数。它更便于其他人阅读,更便于在维护阶段理解,并消除了编写错误的可能性。

function toInt( val ) {
return val & 1;
}


var j = toInt(bool);

编辑- 2014年9月10日

在Chrome中,由于某些原因,使用三元操作符和相同的to操作符的转换速度更快。不知道为什么它更快,但我认为这是某种低级优化,在某个地方是有意义的。

var j = boolValue === true ? 1 : 0;

自己测试:http://jsperf.com/boolean-int-conversion/2

在FireFox和Internet Explorer中,使用我发布的版本通常更快。

编辑- 2017年7月14日

好吧,我不会告诉你该用哪个,不该用哪个。每个该死的浏览器都在用每个方法进行操作的速度上下波动。Chrome在某一时刻实际上有位&版本做得比其他版本好,但突然变得更糟了。我不知道他们在做什么,所以我就把它留给谁管。几乎没有任何理由去关心这样的手术能多快完成。即使在手机平台上,这也是一项毫无意义的操作。

此外,这里有一个新的方法来添加一个“toInt”原型,不能被覆盖。

Object.defineProperty(Boolean.prototype, "toInt", { value: function()
{
return this & 1;
}});

我更喜欢使用数函数。它接受一个对象并将其转换为一个数字。

例子:

var myFalseBool = false;
var myTrueBool = true;


var myFalseInt = Number(myFalseBool);
console.log(myFalseInt === 0);


var myTrueInt = Number(myTrueBool);
console.log(myTrueInt === 1);

你可以在jsFiddle中测试它。

您可以通过简单地扩展布尔原型来做到这一点

Boolean.prototype.intval = function(){return ~~this}

不太容易理解那里发生了什么所以另一个版本会是

Boolean.prototype.intval = function(){return (this == true)?1:0}

你可以做一些事情

document.write(true.intval());

当我使用布尔值存储条件时,我经常将它们转换为位域,在这种情况下,我最终使用了原型函数的扩展版本

Boolean.prototype.intval = function(places)
{
places = ('undefined' == typeof(places))?0:places;
return (~~this) << places
}

你可以这样做

document.write(true.intval(2))

它的输出是4。

依我看,最好的解决办法是:

fooBar | 0

这在asm.js中用于强制整型。

我对所有建议的答案创建了JSperf比较。

TL;DR -当前所有浏览器的最佳选择是:

val | 0;

更新:

现在它们似乎都是一样的,除了Number()函数是最慢的,而最好的是val === true ? 1 : 0;

你也可以添加0,使用shift运算符或xor:

val + 0;
val ^ 0;
val >> 0;
val >>> 0;
val << 0;

这些答案和其他答案的速度相似。

当JavaScript期望一个数字值但接收到一个布尔值时,它会将该布尔值转换为一个数字:true和false分别转换为1和0。所以你可以利用这个;

var t = true;
var f = false;


console.log(t*1); // t*1 === 1
console.log(f*1); // f*1 === 0


console.log(+t); // 0+t === 1 or shortened to +t === 1
console.log(+f); //0+f === 0 or shortened to +f === 0

进一步阅读Javascript权威指南第3.8章的类型转换。

输入的方法是:

Number(true) // 1
Number(false) // 0
let integerVariable = booleanVariable * 1;

我已经测试了所有这些例子,我做了一个基准测试,最后我建议你选择较短的一个,它不会影响性能。

运行在Ubuntu服务器14.04,nodejs v8.12.0 - 26/10/18

    let i = 0;
console.time("TRUE test1")
i=0;
for(;i<100000000;i=i+1){
true ? 1 : 0;
}
console.timeEnd("TRUE test1")




console.time("FALSE test2")
i=0;
for(;i<100000000;i=i+1){
false ? 1 : 0;
}
console.timeEnd("FALSE test2")


console.log("----------------------------")


console.time("TRUE test1.1")
i=0;
for(;i<100000000;i=i+1){
true === true ? 1 : 0;
}
console.timeEnd("TRUE test1.1")




console.time("FALSE test2.1")
i=0;
for(;i<100000000;i=i+1){
false === true ? 1 : 0;
}
console.timeEnd("FALSE test2.1")


console.log("----------------------------")


console.time("TRUE test3")
i=0;
for(;i<100000000;i=i+1){
true | 0;
}
console.timeEnd("TRUE test3")


console.time("FALSE test4")
i=0;
for(;i<100000000;i=i+1){
false | 0;
}
console.timeEnd("FALSE test4")


console.log("----------------------------")


console.time("TRUE test5")
i=0;
for(;i<100000000;i=i+1){
true * 1;
}
console.timeEnd("TRUE test5")


console.time("FALSE test6")
i=0;
for(;i<100000000;i=i+1){
false * 1;
}
console.timeEnd("FALSE test6")


console.log("----------------------------")


console.time("TRUE test7")
i=0;
for(;i<100000000;i=i+1){
true & 1;
}
console.timeEnd("TRUE test7")


console.time("FALSE test8")
i=0;
for(;i<100000000;i=i+1){
false & 1;
}
console.timeEnd("FALSE test8")


console.log("----------------------------")


console.time("TRUE test9")
i=0;
for(;i<100000000;i=i+1){
+true;
}
console.timeEnd("TRUE test9")


console.time("FALSE test10")
i=0;
for(;i<100000000;i=i+1){
+false;
}
console.timeEnd("FALSE test10")


console.log("----------------------------")


console.time("TRUE test9.1")
i=0;
for(;i<100000000;i=i+1){
0+true;
}
console.timeEnd("TRUE test9.1")


console.time("FALSE test10.1")
i=0;
for(;i<100000000;i=i+1){
0+false;
}
console.timeEnd("FALSE test10.1")


console.log("----------------------------")


console.time("TRUE test9.2")
i=0;
for(;i<100000000;i=i+1){
-true*-1;
}
console.timeEnd("TRUE test9.2")


console.time("FALSE test10.2")
i=0;
for(;i<100000000;i=i+1){
-false*-1;
}
console.timeEnd("FALSE test10.2")


console.log("----------------------------")


console.time("TRUE test9.3")
i=0;
for(;i<100000000;i=i+1){
true-0;
}
console.timeEnd("TRUE test9.3")


console.time("FALSE test10.3")
i=0;
for(;i<100000000;i=i+1){
false-0;
}
console.timeEnd("FALSE test10.3")


console.log("----------------------------")


console.time("TRUE test11")
i=0;
for(;i<100000000;i=i+1){
Number(true);
}
console.timeEnd("TRUE test11")


console.time("FALSE test12")
i=0;
for(;i<100000000;i=i+1){
Number(false);
}
console.timeEnd("FALSE test12")


console.log("----------------------------")


console.time("TRUE test13")
i=0;
for(;i<100000000;i=i+1){
true + 0;
}
console.timeEnd("TRUE test13")


console.time("FALSE test14")
i=0;
for(;i<100000000;i=i+1){
false + 0;
}
console.timeEnd("FALSE test14")


console.log("----------------------------")


console.time("TRUE test15")
i=0;
for(;i<100000000;i=i+1){
true ^ 0;
}
console.timeEnd("TRUE test15")


console.time("FALSE test16")
i=0;
for(;i<100000000;i=i+1){
false ^ 0;
}
console.timeEnd("FALSE test16")


console.log("----------------------------")


console.time("TRUE test17")
i=0;
for(;i<100000000;i=i+1){
true ^ 0;
}
console.timeEnd("TRUE test17")


console.time("FALSE test18")
i=0;
for(;i<100000000;i=i+1){
false ^ 0;
}
console.timeEnd("FALSE test18")


console.log("----------------------------")


console.time("TRUE test19")
i=0;
for(;i<100000000;i=i+1){
true >> 0;
}
console.timeEnd("TRUE test19")


console.time("FALSE test20")
i=0;
for(;i<100000000;i=i+1){
false >> 0;
}
console.timeEnd("FALSE test20")


console.log("----------------------------")


console.time("TRUE test21")
i=0;
for(;i<100000000;i=i+1){
true >>> 0;
}
console.timeEnd("TRUE test21")


console.time("FALSE test22")
i=0;
for(;i<100000000;i=i+1){
false >>> 0;
}
console.timeEnd("FALSE test22")


console.log("----------------------------")


console.time("TRUE test23")
i=0;
for(;i<100000000;i=i+1){
true << 0;
}
console.timeEnd("TRUE test23")


console.time("FALSE test24")
i=0;
for(;i<100000000;i=i+1){
false << 0;
}
console.timeEnd("FALSE test24")


console.log("----------------------------")


console.time("TRUE test25")
i=0;
for(;i<100000000;i=i+1){
~~true;
}
console.timeEnd("TRUE test25")


console.time("FALSE test26")
i=0;
for(;i<100000000;i=i+1){
~~false;
}
console.timeEnd("FALSE test26")


console.log("----------------------------")


console.time("TRUE test25.1")
i=0;
for(;i<100000000;i=i+1){
~true*-1-1;
}
console.timeEnd("TRUE test25.1")


console.time("FALSE test26.1")
i=0;
for(;i<100000000;i=i+1){
~false*-1-1;
}
console.timeEnd("FALSE test26.1")


console.log("----------------------------")


console.time("TRUE test27")
i=0;
for(;i<100000000;i=i+1){
true/1;
}
console.timeEnd("TRUE test27")


console.time("FALSE test28")
i=0;
for(;i<100000000;i=i+1){
false/1;
}
console.timeEnd("FALSE test28")

结果

TRUE test1: 93.301ms
FALSE test2: 102.854ms
----------------------------
TRUE test1.1: 118.979ms
FALSE test2.1: 119.061ms
----------------------------
TRUE test3: 97.265ms
FALSE test4: 108.389ms
----------------------------
TRUE test5: 85.854ms
FALSE test6: 87.449ms
----------------------------
TRUE test7: 83.126ms
FALSE test8: 84.992ms
----------------------------
TRUE test9: 99.683ms
FALSE test10: 87.080ms
----------------------------
TRUE test9.1: 85.587ms
FALSE test10.1: 86.050ms
----------------------------
TRUE test9.2: 85.883ms
FALSE test10.2: 89.066ms
----------------------------
TRUE test9.3: 86.722ms
FALSE test10.3: 85.187ms
----------------------------
TRUE test11: 86.245ms
FALSE test12: 85.808ms
----------------------------
TRUE test13: 84.192ms
FALSE test14: 84.173ms
----------------------------
TRUE test15: 81.575ms
FALSE test16: 81.699ms
----------------------------
TRUE test17: 81.979ms
FALSE test18: 81.599ms
----------------------------
TRUE test19: 81.578ms
FALSE test20: 81.452ms
----------------------------
TRUE test21: 115.886ms
FALSE test22: 88.935ms
----------------------------
TRUE test23: 82.077ms
FALSE test24: 81.822ms
----------------------------
TRUE test25: 81.904ms
FALSE test26: 82.371ms
----------------------------
TRUE test25.1: 82.319ms
FALSE test26.1: 96.648ms
----------------------------
TRUE test27: 89.943ms
FALSE test28: 83.646ms

试一试

val*1

let t=true;
let f=false;


console.log(t*1);
console.log(f*1)

在我的上下文中,React Native,我从布尔获取不透明度值,最简单的方法:使用一元+运算符。

+ true; // 1
+ false; // 0

这将布尔值转换为数字;

style={ opacity: +!isFirstStep() }

+!!允许你在一个变量上应用它,即使它是undefined:

+!!undefined    // 0
+!!false        // 0
+!!true         // 1


+!!(<boolean expression>)  // 1 if it evaluates to true, 0 otherwise

TL;DR:避免Number构造函数和+bool;默认使用简单的if;如果你的项目中的基准测试以这种方式做得更好,请使用bool | 01 * bool

这是一个相当老的问题,有很多有效的答案。我注意到这里所有的基准测试都是不相关的——没有一个会考虑分支 预测。此外,现在JS引擎不只是简单地解释代码,他们JIT 编译本机机器码,并在执行之前优化它。这意味着,除了分支预测,编译器甚至可以用表达式的最终值替换表达式。

那么,这两个因素是如何影响布尔到整数转换的性能的呢?让我们一探究竟!在开始基准测试之前,了解基准测试的对象是很重要的。对于转换,我们使用以下7种转换方法:

  • 数字构造函数:Number(bool)
  • If语句(使用三元):bool ? 1 : 0
  • 一元运算符+: +bool
  • 位OR: bool | 0
  • 位与:bool & 1
  • 位双NOT: ~~bool
  • 数字乘法:bool * 1

“Conversion"意味着将false转换为0,将true转换为11。每种转换方法运行100000次,测量操作/毫秒。在下表中,转换方法将根据其结果进行分组。结果后的百分比表示在同一浏览器中,该方法与最快方法相比有多慢。如果没有百分比,该方法要么是最快的,要么差异可以忽略不计(<0.01%)。测试运行在一台16英寸的Macbook Pro电脑上,配有Apple M1 Pro 10核CPU和16GB内存。浏览器有Chrome 102、Firefox 101和Safari 15.5。

第一个基准转换常量true:

< span style=" font - family:宋体;"> < / th方法> < span style=" font - family:宋体;"Chrome (V8) < / th > > < span style=" font - family:宋体;"Firefox (Spidermonkey) < / th > > < span style=" font - family:宋体;"> Safari (Webkit) < / th > < span style=" font - family:宋体;"> Number(bool) td > < / < span style=" font - family:宋体;"> bool ? 1 : 0 td > < / < td风格= " text-align:左;" > < / td > 31592.8 - 0.48% < span style=" font - family:宋体;"> +bool td > < / < td风格= " text-align:左;" > < / td > 31332.57 - 1.3% < td风格= " text-align:左;" > < / td > 4463.41 - 3.02% < span style=" font - family:宋体;"> bool | 0 td > < / < td风格= " text-align:左;" > < / td > 31488.5 - 0.81% . < span style=" font - family:宋体;"> bool & 1 td > < / < span style=" font - family:宋体;"> ~~bool td > < / . < span style=" font - family:宋体;"> bool * 1 td > < / < td风格= " text-align:左;" > < / td > 31374.4 - 1.17% < td风格= " text-align:左;" > < / td > 4444.05 - 3.45% .
31745.89 < td风格= " text-align:左;" > < / td > 392.35 - 91.48% 31231.79
4602.64 27533.47 - 11.84%
27378.7 - 12.34%
27222 - 12.84%
31383.17 - 1.14% < td风格= " text-align:左;" > < / td > 4459.64 - 3.11% 27317.41 - 12.53%
31265.85 - 1.51% < td风格= " text-align:左;" > < / td > 4442.35 - 3.48% 27434.72 - 12.16%
基准来看看。

< span style=" font - family:宋体;"> < / th方法> < span style=" font - family:宋体;"Chrome (V8) < / th > > < span style=" font - family:宋体;"Firefox (Spidermonkey) < / th > > < span style=" font - family:宋体;"> Safari (Webkit) < / th > < span style=" font - family:宋体;"> Number(bool) td > < / < td风格= " text-align:左;" > < / td > 1648.83 - 2.26% . font - family:宋体 . font - family:宋体; < span style=" font - family:宋体;"> bool ? 1 : 0 td > < / < td风格= " text-align:左;" > < / td > 804.27 - 52.32% . font - family:宋体 . font - family:宋体; >1294.02 - 83.85% . font - family:宋体 < span style=" font - family:宋体;"> +bool td > < / < td风格= " text-align:左;" > < / td > 1670.79 - 0.95% < td风格= " text-align:左;" > < / td > 7753.99 - 3.25% < span style=" font - family:宋体;"> bool | 0 td > < / < td风格= " text-align:左;" > < / td > 1668.22 - 1.11% < td风格= " text-align:左;" > < / td > 7764.81 - 3.12% < span style=" font - family:宋体;"> bool & 1 td > < / < td风格= " text-align:左;" > < / td > 1675.52 - 0.67% . > /td> . < span style=" font - family:宋体;"> ~~bool td > < / < td风格= " text-align:左;" > < / td > 1676.24 - 0.63% . < td风格= " text-align:左;" > < / td > 7669.48 - 4.31% < span style=" font - family:宋体;"> bool * 1 td > < / . . < td风格= " text-align:左;" > < / td > 7751.48 - 3.28%
8014.69
2057.94
2054.17
2056.767193.08 - 10.25%
2056.18
2060.88

现在的结果更加一致了。我们在不同浏览器中看到类似的三元if、位和乘法方法,并且Number构造函数在Firefox上的性能最差。三元在生成分支时落在后面。Safari似乎是我们整体表现最好的,每种方法都能产生极快的结果!

现在让我们看看分支预测如何通过下面的基准影响我们的结果,其中我们将布尔变量改为Math.random() < 0.01,这意味着1% true, 99% false

< span style=" font - family:宋体;"> < / th方法> < span style=" font - family:宋体;"Chrome (V8) < / th > > < span style=" font - family:宋体;"Firefox (Spidermonkey) < / th > > < span style=" font - family:宋体;"> Safari (Webkit) < / th > < span style=" font - family:宋体;"> Number(bool) td > < / < td风格= " text-align:左;" > < / td > 1643.13 - 1.68% . font - family:宋体 . font - family:宋体; . < span style=" font - family:宋体;"> bool ? 1 : 0 td > < / < td风格= " text-align:左;" > < / td > 1590.55 - 4.83% < td风格= " text-align:左;" > < / td > 1970.66 - 4.32% < td风格= " text-align:左;" > < / td > 7119.59 - 11.8% < span style=" font - family:宋体;"> +bool td > < / < td风格= " text-align:左;" > < / td > 1662.09 - 0.55% . < td风格= " text-align:左;" > < / td > 7762.03 - 3.84% < span style=" font - family:宋体;"> bool | 0 td > < / < td风格= " text-align:左;" > < / td > 7743.95 - 4.06% < span style=" font - family:宋体;"> bool & 1 td > < / < td风格= " text-align:左;" > < / td > 1661.09 - 0.61% . < td风格= " text-align:左;" > < / td > 7454.45 - 7.65% < span style=" font - family:宋体;"> ~~bool td > < / . . < td风格= " text-align:左;" > < / td > 7787.38 - 3.52%
8071.65
2054.09
1669.35 2051.85
2057.62
1662.94 - 0.5% 2059.65 bool * 1 td > < / 1671.28 2048.21

意想不到的?预期?我认为是后者,因为在这种情况下,分支预测在几乎所有情况下都是成功的,因为三元if和位hack之间的差异较小。其他的结果都是一样的,这里就不多说了。我仍然要指出Number在Firefox中的可怕性能——为什么?

这将我们带回到最初的问题:如何在Javascript中将bool类型转换为int类型?以下是我的建议:

  • 一般使用if语句。不要自作聪明——浏览器通常会做得更好,而且通常意味着大多数情况。它们是这里所有方法中最易读、最清晰的。在可读性方面,也许可以使用if (bool)来代替那个丑陋的三元!我希望Javascript有生锈Python有…
  • 必要时再用剩下的。也许你的项目中的基准测试执行不达标,并且你发现一个讨厌的if会导致糟糕的性能-如果是这种情况,请随意进入无枝的 编程!但是不要陷得太深,没有人会从-1 * (a < b) + 1 * (a > b)这样的事情中受益,相信我。

还有一些细节:

  • 避免Number(bool)。虽然Chromium平台(Chrome + Edge)在全球拥有约68%的市场份额,Safari占19%,Firefox仅占3.6%,但有足够多的其他快速运行的方法不会完全牺牲你的用户比例。火狐拥有7%的桌面市场份额,这意味着有1.73亿用户。
  • 在旧的基准测试中,+bool在Firefox中的表现与Number一样糟糕,也许也要考虑到这一点——在所有浏览器中,在所有情况下,逐位hack和乘法都能获得一致的性能结果。bool | 0有最好的机会为其他开发人员所熟悉。

我将永远感谢你一直读到最后——这是我第一个更长的、重要的StackOverflow回答,如果它有帮助和深刻的见解,对我来说意味着世界。如果你发现任何错误,请随时纠正我!

以前的基准测试工具提供了模糊的结果,没有测量单位。我对它进行了更改,并为Safari添加了基准测试,这对结论产生了影响。


  1. 定义了转换,因为它并不真正清楚布尔到整数的含义。例如, 根本不支持这种转换

将建议的方法放在jsben.ch中: https://jsben.ch/d33N1 . < / p >

每次测试都会给出不同的结果,但每次测试中最好的方法是位操作:0|bool / bool|0 / 1&bool / 1&bool / ~~bool

所有浏览器都支持,支持输入布尔值或布尔值的字符串表示形式

var yourVarAsStringOrBoolean;
yourVarAsStringOrBoolean = "true";   //1
yourVarAsStringOrBoolean = "True";   //1
yourVarAsStringOrBoolean = "false";  //0
yourVarAsStringOrBoolean = false;    //0


var resultAsInterger = Number(JSON.parse(yourVarAsStringOrBoolean.toString().toLowerCase()));

使用Chrome控制台检查它,它的工作

Number(JSON.parse(false.toString().toLowerCase()));
Number(JSON.parse("TRUE".toString().toLowerCase()));

在JavaScript中,布尔到整数的转换可以通过以下方式完成:

  1. Using Number()
  2. 使用三元
  3. 使用一元运算符
  4. Using算术运算符 .
  5. Using Bitwise Operators .
  6. 使用按位移位操作符 .

在之前的回答中,其中一些已经被涵盖,但是,你可以发现一些缺失的内容如下:

// using arithmetic operators


true + 0; // 1
false + 0; // 0


true - 0; // 1
false - 0; // 0


true * 1 // 1
false * 1 // 0


true / 1; // 1
false / 1; // 0
// using bitwise operators


true & 1; // 1
false & 1; // 0


true | 0; // 1
false | 0; // 0


true ^ 0; // 1
false ^ 0; // 0
// using bitwise shift operators


true >> 0; // 1
false >> 0; // 0


true >>> 0; // 1
false >>> 0; // 0


true << 0; // 1
false << 0; // 0

这些工作是因为JavaScript在执行这些操作时在内部将布尔值强制转换为整数等价物。

需要注意的一点是,当你不确定变量总是具有布尔值时,所有这些方法(除了使用三元运算符)都可能返回NaN

为那些有兴趣了解更多的人写了博客