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

时间:2011-10-19 11:34:31

标签: javascript numbers integer boolean type-conversion

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

19 个答案:

答案 0 :(得分:375)

使用unary + operator,将其操作数转换为数字。

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

当然,请注意,您仍应该清理服务器端的数据,因为无论客户端代码说什么,用户都可以向服务器发送任何数据。

答案 1 :(得分:285)

Javascript有一个你可以使用的三元运算符:

var i = result ? 1 : 0;

答案 2 :(得分:97)

Imho最好的解决方案是:

fooBar | 0

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

答案 3 :(得分:46)

我更喜欢使用Number function。它需要一个对象并将其转换为数字 例如:

var myFalseBool = false;
var myTrueBool = true;

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

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

或者在jsFiddle中运行。

答案 4 :(得分:36)

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

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

val | 0;

<强>更新

似乎这几天它们都完全相同,只是Number()函数最慢,而最好val === true ? 1 : 0;

答案 5 :(得分:31)

执行此操作的键入方式是:

Number(true) // 1
Number(false) // 0

答案 6 :(得分:26)

我今天刚遇到这条捷径。

~~(真)

~~(假)

人们比我能解释的更聪明:

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

答案 7 :(得分:15)

当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章。

答案 8 :(得分:12)

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

var j = bool & 1;

处理常量问题的更快方法是创建一个函数。它更容易被其他人阅读,更好地在维护阶段理解,并摆脱写错的可能性。

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

var j = toInt(bool);

编辑 - 2014年9月10日

由于某些原因,使用与运营商相同的三元运营商进行转换的速度较快。对于为什么速度更快没有任何意义,但我认为它是某种低级优化,在某个地方有意义。

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

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

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

编辑 - 2017年7月14日

好的,我不打算告诉你应该或不应该使用哪一个。每个疯狂的浏览器一直在上下起伏,他们用各种方法进行操作的速度有多快。 Chrome在某一点实际上是按位&amp;版本做得比其他版本好,但后来突然变得更糟。我不知道他们在做什么,所以我只想把它留在谁在意。几乎没有理由关心这样的操作有多快。即使在移动设备上也没什么可操作的。

此外,这是添加“toInt”原型的新方法,无法覆盖。

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

答案 9 :(得分:11)

一元+运算符将处理此问题:

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

在存储它之前,您自然希望在服务器上进行完整性检查,因此无论如何这可能是一个更明智的地方。

答案 10 :(得分:9)

您还可以添加0,使用移位运算符或xor:

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

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

答案 11 :(得分:5)

TL;DR:避免 Number 构造函数,一元 +;一直使用简单的 if;如果您的项目中的基准以这种方式做得更好,则采用 bool | 01 * bool

这是一个很老的问题,有很多有效的答案。我注意到这里的所有基准都是无关紧要的——没有一个考虑到 branch prediction。此外,如今,JS 引擎不再简单地解释代码,而是将其 JIT compile 转换为本地机器代码并在执行之前对其进行优化。这意味着,除了分支预测之外,编译器甚至可以用它们的最终值替换表达式。

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

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

“转换”表示将 false 转换为 0,将 true 转换为 11。每种转换方法运行 100000 次,测量操作数/毫秒。在下表中,转换方法将根据其结果进行分组。结果来自我的机器,它的 CPU 为 AMD Ryzen 7 4800HS。

第一个 benchmark 转换常量 true

<头>
方法 Edge/Chromium (V8) Firefox (Spidermonkey)
Number(bool) 83103 1088
bool ? 1 : 0 83073 7732
+bool 83372 1043
bool | 0 83479 9344
bool & 1 83242 9354
~~bool 83293 9316
bool * 1 83504 9316

有趣! V8 显示了一些巨大的数字,它们都大致相同! Spidermonkey 并没有真正发光,但我们可以看到按位和乘法技巧是第一位的,如果第二位是三元。什么是外卖? Chrome 浏览器设法用简单的值 1 替换了我们的转化。这种优化将发生在我们可以将布尔值替换为常量值的地方。

以上不是我们在实际项目中会遇到的情况。所以让我们改变我们的变量:bool 现在是 Math.random() < 0.5。这会产生 50% 的机会 true,50% 的 false。我们的结果会改变吗?让我们运行这个 benchmark 来看看。

<头>
方法 Edge/Chromium (V8) Firefox (Spidermonkey)
Number(bool) 2405 662
bool ? 1 : 0 1482 1580
+bool 2386 673
bool | 0 2391 2499
bool & 1 2409 2513
~~bool 2341 2493
bool * 1 2398 2518

现在的结果更加一致。我们看到三元 if、bitwise 和乘法方法的数字相似,但 Number 构造函数和一元 + 在 V8 上表现更好。我们可以从数字推测 V8 用它用于按位技巧的任何指令替换它们,但在 Spidermonkey 中,这些函数完成了所有工作。

我们还没有解决我们上面提到的一个因素:分支预测。让我们将这个 benchmark 中的布尔变量更改为 Math.random() < 0.01,这意味着 1% true, 99% false

<头>
方法 Edge/Chromium (V8) Firefox (Spidermonkey)
Number(bool) 2364 865
bool ? 1 : 0 2352 2390
+bool 2447 777
bool | 0 2421 2513
bool & 1 2400 2509
~~bool 2446 2501
bool * 1 2421 2497

出乎意料?预期的?我会说后者,因为在这种情况下,分支预测几乎在所有情况下都是成功的,考虑到三元 if 和按位黑客之间的微小差异。其他结果都一样,这里就不多说了。

这项努力让我们回到了最初的问题:如何在 Javascript 中将 bool 转换为 int?以下是我的建议:

  • 避免使用 Number(bool)+bool。这 2 种方法在幕后做了很多工作,即使 Chrome 设法在我们的基准测试中对其进行了优化,Firefox 却没有,而且在某些情况下,编译器可能不会完成这些优化。除此之外,并不是每个人都在使用 Chrome!我还是得忍受,不是吗?...
  • 一般使用 if 语句。不要变得聪明 - 浏览器通常会做得更好,并且通常意味着大多数情况。它们是这里所有方法中最易读和最清晰的。当我们处于可读性时,也许使用 if (bool) 而不是那个丑陋的三元!我希望 Javascript 拥有 RustPython 所拥有的...
  • 在真正需要时使用其余部分。也许您项目中的基准测试不符合标准,并且您发现令人讨厌的 if 导致性能不佳 - 如果是这种情况,请随时进入 branchless programming!但是不要在那个兔子洞里钻得太深,相信我,没有人会从 -1 * (a < b) + 1 * (a > b) 之类的东西中受益。

我将永远感谢您阅读到最后——这是我第一个更长、更重要的 StackOverflow 答案,如果它对我有帮助和洞察力,它对我来说意味着整个世界。如果您发现任何错误,请随时纠正我!


  1. 定义了转换,因为它并不清楚布尔值到整数的含义。例如,Go does not support this conversion at all

答案 12 :(得分:4)

你可以通过简单地扩展布尔原型

来做到这一点
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作为输出。

答案 13 :(得分:4)

+!!允许您将此变量应用于变量undefined

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

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

答案 14 :(得分:3)

let integerVariable = booleanVariable * 1;

答案 15 :(得分:2)

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

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

这会将布尔值转换为数字;

style={ opacity: +!isFirstStep() }

答案 16 :(得分:0)

尝试

val*1

let t=true;
let f=false;

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

答案 17 :(得分:0)

如果要让整数x值在1到0和0到1之间变化 您可以使用  (x +1)%2

答案 18 :(得分:-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