【问题标题】:How to do this with the ternary operator in one line?如何在一行中使用三元运算符?
【发布时间】:2015-09-15 01:04:09
【问题描述】:

考虑 int num 的这个 const 声明:

int main() {
    bool a = true, b = false;
    // ...
    const int num = a ? (b? 2 : 4) : 4;
    std::cout << num;
}

我想要const int num 遵循这个真值表(我很抱歉已经从我的原始问题中编辑了它以反映我程序中的模式):

              b
  a      true   false
true      2      4
false     4      2

如何修改上面的const int num 声明以使用三元运算符实现这一点?我知道如何使用 lambda 函数和嵌套的 if 语句或 switch 语句在 lambda 函数中声明这样的 num 为 const,但我只想知道如何使用三元运算符来做到这一点。作为奖励,如果要使用 3 个或更多这样的布尔值(在真值表中没有特定模式)怎么办?

【问题讨论】:

  • a ? (b? 2 : 3) : (b ? 4 : 5);

标签: c++ operator-keyword ternary


【解决方案1】:

David Haim 的答案非常适合真值表中的许多其他值。然而,在这个特定实例中,我们可以利用一个易于识别的数学关系:

const int num = (a ? 2 : 4) + (b ? 0 : 1);

但是,我们可能并不总是在真值表中拥有如此容易识别的关系。


上面的表达式是基于问题的原始真值表,看起来像这样:

              b
  a      true   false
true      2      3
false     4      5

鉴于此真值表:

b 真假 真的 2 4 假 4 2

还有另一种方法可以返回正确的值:

const int num (a == b) ? 2 : 4

这不是真正的数学。只是简单地认识到当ab 相同时,我们想要2,但是当ab 不同时,我们想要4。此真值表与 == 运算符的真值表完全相同,我们只是返回 2/4 而不是 true/false

【讨论】:

  • @nhgrif。我编辑了我的问题以反映我程序中的实际模式。所以当 b 为假时,2,4 被翻转。那么我们可以利用什么数学关系来写 b 一次?
【解决方案2】:

在这种特殊情况下,我会选择:

const int num = (a == b) ? 2 : 4;

【讨论】:

  • 没错,我的错。但是了解一般情况的解决方案也很好。
【解决方案3】:

你可以像这样写声明

const int num = ( a ^ b ) ? 4 : 2;

至少比它更清晰

const int num = a ? (b? 2 : 4) : 4;

这是一个演示程序

#include <iostream>

int main()
{
    std::cout << ( false ^ false ? 4 : 2 ) << std::endl;
    std::cout << ( true  ^ false ? 4 : 2 ) << std::endl;
    std::cout << ( false ^ true  ? 4 : 2 ) << std::endl;
    std::cout << ( true  ^ true  ? 4 : 2 ) << std::endl;
}

程序输出是

2
4
4
2

【讨论】:

    【解决方案4】:
    const int num = a ? (b? 2 : 3) : (b? 4: 5);
    

    编辑:

    作为奖励,如果要使用 3 个或更多这样的 bool 值会怎样?

    我根本不会使用这样的语法。 我会将我的表声明为

    int truthTable[2][2]..[2] = {{..},...{..}}
    

    现在很简单:
    int res = truthTable[!true][!false]..[!true]

    !true 会变成0!false 会变成1,然后从数组中拉取正确的值。

    【讨论】:

    • b 是否在这里评估过一次或两次?有什么方法可以只写一次b
    • 我不知道,我认为编译器要么根本不优化,要么部分优化,要么完全优化掉代码。因此-我们不知道。
    • 看生成的程序集就知道了。
    • 视情况而定。尺寸是你的问题吗?速度?代码行?我认为你应该指定你真正的问题才能得到真正的答案
    • @prestokeys 澄清一下,gcc 似乎没有使用-O2-O3 开关两次评估b。如果你愿意,它正在做一些非常简洁的事情,view it here
    猜你喜欢
    • 2019-10-08
    • 2022-01-04
    • 2020-05-10
    • 2022-01-04
    • 2020-12-19
    • 2010-12-13
    • 1970-01-01
    • 1970-01-01
    • 2021-03-09
    相关资源
    最近更新 更多