Подтвердить что ты не робот

Преобразование Boolean в Integer в Java без If-Statement

Мне интересно, есть ли способ конвертировать логическое значение в int без использования операторов if (чтобы не разрывать конвейер). Например, я мог написать

int boolToInt( boolean b ){
  if ( b )
    return 1
  return 0

Но мне интересно, есть ли способ сделать это без инструкции if, например Python

bool = True 
num = 1 * ( bool )

Я также думаю, что вы могли бы сделать

boolean bool = True;
int myint = Boolean.valueOf( bool ).compareTo( false );

Это создает дополнительный объект, однако, поэтому он действительно расточительный, и я нашел его еще медленнее, чем способ if-statement (который не обязательно неэффективен, просто имеет одну слабость).

4b9b3361

Ответ 1

Вы не можете использовать логическое значение, отличное от if. Однако это не означает, что на уровне сборки будет ветвь.

Если вы проверяете скомпилированный код этого метода (кстати, используя return b ? 1 : 0; для компиляции с теми же инструкциями), вы увидите, что он не использует скачок:

0x0000000002672580: sub    $0x18,%rsp
0x0000000002672587: mov    %rbp,0x10(%rsp)    ;*synchronization entry
0x000000000267258c: mov    %edx,%eax
0x000000000267258e: add    $0x10,%rsp
0x0000000002672592: pop    %rbp
0x0000000002672593: test   %eax,-0x2542599(%rip)        # 0x0000000000130000
                                                ;   {poll_return}
0x00000000025b2599: retq  

Примечание: это сервер hotspot 7 - вы можете получать разные результаты на другой виртуальной машине.

Ответ 2

Используйте оператор?: ( b ? 1 : 0 )

Ответ 3

Вы можете использовать тернарный оператор:

return b ? 1 : 0;

Если это считается "если", и учитывая, что это "головоломка", вы можете использовать такую ​​карту:

return new HashMap<Boolean, Integer>() {{
    put(true, 1);
    put(false, 0);
}}.get(b);

Хотя теоретически реализация HashMap не требует использования if, на самом деле это делает. Тем не менее, "if" не находится в вашем коде.

Конечно, для повышения производительности вы бы:

private static Map<Boolean, Integer> map = new HashMap<Boolean, Integer>() {{
    put(true, 1);
    put(false, 0);
}};

Тогда в методе:

return map.get(b);

Ответ 4

В противном случае вы можете использовать метод Apache Commons BooleanUtils.toInteger, который работает как прелесть...

// Converts a boolean to an int specifying the conversion values.    
static int  toInteger(boolean bool, int trueValue, int falseValue)

// Converts a Boolean to an int specifying the conversion values.
static int  toInteger(Boolean bool, int trueValue, int falseValue, int nullValue)

Ответ 5

Я нашел решение по структуре. Используйте сравнение для Boolean.

// b = Your boolean result
// v will be 1 if b equals true, otherwise 0
int v = Boolean.compare(b, false);

Ответ 6

Это невозможно напрямую, но не в Java. Вы можете напрямую рассмотреть int или byte вместо boolean, если вам действительно нужно избегать ветки.

Также возможно, что виртуальная машина достаточно умна, чтобы исключить ветвь (if или ?:) сама в этом случае, так как внутреннее представление boolean вполне вероятно будет буквальным 1 или 0 в любом случае. Вот статья о том, как исследовать сгенерированный собственный машинный код для Oracle JDK, и если вам нужна скорость, убедитесь, что вы используете "сервер" JVM поскольку он выполняет более агрессивную оптимизацию, чем "клиентский".

Ответ 7

Я не могу сказать, что рекомендую это. Он как медленнее, чем троичный оператор сам по себе, и он слишком умный, чтобы называться хорошим программированием, но вот это:

-Boolean.FALSE.compareTo(value)

Он использует тернар под обложками (несколько вызовов метода позже), но это не в вашем коде. Справедливости ради, я был бы готов поспорить, что там есть какая-то ветвь в исполнении Python (хотя я, вероятно, делаю ставку только на никель;)).

Ответ 8

Вы можете попробовать использовать тернарный оператор следующим образом

int value = (flag==true ? 1 : 0);

Ответ 9

Поскольку вы не хотите, чтобы решение if/else ваше выражение было совершенным, хотя я бы слегка его изменил

int myint = Boolean.valueOf( bool ).compareTo( Boolean.FALSE );

Нет создания объекта, Boolean.valueOf(boolean b) возвращает либо Boolean.TRUE, либо Boolean.FALSE, см. API

Ответ 10

Разумная альтернатива исчислению троичности, чтобы избежать "if":

private static Boolean[] array = {false, true};

int boolToInt( boolean b ){
    return Arrays.binarySearch(array, b);
}

Обратите внимание, что я рассматриваю этот вопрос с "головоломкой", поэтому, если я сам его кодирую, я бы использовал тройную версию.