Я просматривал код партнера и нашел это заявление IF.

if (((x == 0) && (y == 0)) || y == 0) { 
            do something
        }

Поправьте меня, если я ошибаюсь, но не является ли первая часть IF избыточной?

1
TiraULTI 31 Авг 2017 в 19:17

6 ответов

Лучший ответ

Используйте таблицу истинности:

╔════════╦════════╦══════════════════════════════════╗
║ x == 0 ║ y == 0 ║ ((x == 0) && (y == 0)) || y == 0 ║
╠════════╬════════╬══════════════════════════════════╣
║      0 ║      0 ║                                0 ║
║      0 ║      1 ║                                1 ║
║      1 ║      0 ║                                0 ║
║      1 ║      1 ║                                1 ║
╚════════╩════════╩══════════════════════════════════╝

Ясно, что часть x == 0 не имеет значения, и то, что у вас есть, эквивалентно

if (y == 0) {
    ...
}
7
arshajii 31 Авг 2017 в 16:29

Да, первая часть избыточна. Вторая часть (после ||) вернет true, если y равен 0, независимо от значения x's. Это условие может быть упрощено до

if (y == 0) {
    doSomething();
}

Кстати, стоит отметить, что любая полуприличная IDE предупреждает вас об этой избыточности или, по крайней мере, может быть настроена для этого. Если вы не получаете такого предупреждения, рекомендуется проверить настройки вашей IDE.

0
Mureinik 31 Авг 2017 в 16:20

Вы правы, это эквивалентно

if (y == 0) { 
    //do something
}

Вы можете составить таблицу возможных назначений. Я использую 1, чтобы представить любое целое число, которое не 0.

x  y  (((x == 0) && (y == 0)) || y == 0)
-  -  ----------------------------------
0  0  True
0  1  False
1  0  True
1  1  False

Только когда y = 0, все выражение оценивается как True, так что вы можете также изменить его на (y == 0)

1
Reuben Crimp 31 Авг 2017 в 16:19

Я бы порекомендовал использовать unit test.

boolean isIt(int x, int y) {
 if (((x == 0) && (y == 0)) || y == 0) { 
    return true;
 }
 return false;
}

@Test
public void test1() {
 boolean result = isIt(1, 0);
 assertTrue(result);
}

@Test
public void test1() {
 boolean result = isIt(0, 0);
 assertTrue(result);
}

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

0
alayor 31 Авг 2017 в 16:37

Да, в этом случае это избыточно, поскольку ни одно из условий не имеет побочных эффектов, и если первая часть истинна, вторая часть истинна.

Если, однако, в заявлении были побочные эффекты, то это не всегда так из-за короткого замыкания:

if( (doX() == 0 && doY() == 0) || doY() == 0 ) { ... }

В этом случае, если doX() не возвращает 0, правая часть && не будет оценена, поэтому doY() будет выполнен только один раз. Когда doX() возвращает 0, а первый doY() не возвращает 0, doY() будет выполнен дважды.

3
clcto 31 Авг 2017 в 16:24

Знаешь что? Просто нарисуйте таблицу истинности выражения с и без первой части выражения if.

Давайте предположим

a : x == 0
b : y == 0
c : a && b
d : (a && b) || b

Таким образом, таблица истинности для a, b, c и d показана ниже.

 a | b | c | d |
----------------
 0 | 0 | 0 | 0
----------------
 0 | 1 | 0 | 1
----------------
 1 | 0 | 0 | 0
----------------
 1 | 1 | 1 | 1  

По столу можно было легко судить. Я обычно просто использую уменьшенное выражение на карте Карно. Если бы вы, ребята, могли это сделать, то не было бы времени на споры.

0
cdaiga 31 Авг 2017 в 16:31