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

Оператор && ведет себя как || оператор

Я начинаю, и я пытаюсь запустить программу, которая печатает все числа от 1 до N (ввод пользователя), за исключением тех, которые делятся на 3 и 7 одновременно. Однако мой код делает то, что он печатает числа от 1 до N, за исключением тех, которые делятся на 3 или 7. Я некоторое время изучал его, и я понятия не имею, почему он это делает. Пожалуйста, объясните мне, где я ошибаюсь.

static void Main(string[] args)
{
    int n = 0;
    int a = 0;
    n = Convert.ToInt32(Console.ReadLine());
    while (a <= n)
    {
        a++;
        if (a % 3 != 0 && a % 7 != 0)
        {
            Console.WriteLine(a);
        }
    }
    Console.ReadKey();
}

Когда я меняю знаки оператора if на ==, оператор && работает правильно, но если знак !=, он просто действует как оператор ||, так что меня еще больше смущает. Проблема, скорее всего, в состоянии, но я не вижу, что с ней не так.

4b9b3361

Ответ 1

"За исключением чисел, которые делятся на 3 и 7 одновременно", можно разбить следующим образом:

"divisible by 3 and 7 at the same time" может быть выражен как:

"(divisible by 3 and divisible by 7)"

"Except" может быть выражен как "Not".

Итак, вы получаете:

Not (divisible by 3 and divisible by 7)

", делящийся на 3", равен (a % 3) == 0

", делимое на 7", (a % 7) == 0

Дарение:

Not ( (a % 3) == 0 and (a % 7) == 0)

В С# Not становится !, а and становится &&, поэтому вы можете написать все на С# как:

if (!((a % 3) == 0 && (a % 7) == 0))


Сравните с вашим неправильным:

if (a % 3 != 0 && a % 7 != 0)

Последнее неверно, потому что это означает:

if (the number is not divisible by 3) and (the number is not divisible by 7).

то есть. это означает "Print the number if it is neither divisible by 3 nor divisible by 7", что означает "don't print the number if it divisible by 3 or 7".

Чтобы понять, почему сначала рассмотрим число 6:

6 is not divisible by 3? = false (because 6 *is* divisible by 3)
6 is not divisible by 7? = true (because 6 is *not* divisible by 7)

Итак, это решается до if false and true, который, конечно, false.

Этот результат также применим к любому другому числу, делящемуся на 3, поэтому никакие числа, делящиеся на 3., будут напечатаны.

Теперь рассмотрим число 14:

14 is not divisible by 3? = true (because 14 is *not* divisible by 3)
14 is not divisible by 7? = false (because 14 *is* divisible by 7)

Итак, это разрешает if true and false, что, конечно, false.

Этот результат также применим к любому другому числу, делящемуся на 7, поэтому числа, делящиеся на 7, будут напечатаны.

Надеюсь, вы сразу поймете, почему это неправильно. Если нет, рассмотрим этот эквивалентный пример:


Предположим, у нас есть четыре человека: Том Плотник, Дик Плотник, Гарри Мясник и Том Мясник.

Этот вопрос эквивалентен тому, который вы задаете:

 Name every person who is (not called Tom and is not a Butcher)

И вы должны уметь видеть, что это так же, как спрашивать:

Name every person except (anyone called Tom or anyone who is a Butcher)

В обоих случаях ответом является Dick the Carpenter.

Вопрос, который вы должны задать,:

Name every person except (anyone called Tom who is also a butcher)

На что отвечает Том Плотник, Дик Карпентер и Гарри Мясник.


Сноска: законы Де Моргана

Второй закон гласит, что:

"not (A or B)" is the same as "(not A) and (not B)"

Это эквивалент моего примера выше, где:

Name every person except (anyone called Tom or anyone who is a Butcher)

является эквивалентом:

Name every person who is (not called Tom and is not a Butcher)

где A - anyone called Tom, а B - anyone who is a butcher, а Not записывается как except.

Ответ 2

Вы должны прочитать законы Де Моргана

"not (A и B)" совпадает с "(не A) или (не B)"

и

"not (A или B)" совпадает с "(не A) и (не B)".

a % 3 != 0 && a % 7 != 0 истинно, если a не делится на 3 (a % 3 != 0) и не делится на 7 (a % 7 != 0). Таким образом, все a, которые делятся на 3 или 7 (3,6,7,9,12,14,...), делают все выражение ложным. Вы можете перефразировать его как !(a % 3 == 0 || a % 7 == 0)

Ответ 3

Должно быть:

if ( !(a % 3 == 0 && a % 7 == 0) )
{
    Console.WriteLine(a);
}

Это означает точно: все числа, за исключением тех, которые делятся на 3 и 7 в то же время.

Вы также можете перефразировать его как:

if ( a % 3 != 0 || a % 7 != 0 )
{
    Console.WriteLine(a);
}

Ответ 4

Что ты сказал:

   if not (divisible by 3 and divisible by 7) then print

Что вы написали:

   if not divisible by 3 and not divisible by 7 then print

Не то же самое. Аристотель сначала подумал об этом, Август Де Морган написал законы 158 лет назад, применил оператор not к операндам и инвертировал логическую операцию:

   if not divisible by 3 or not divisible by 7 then print

Что производит:

   if (a % 3 != 0 || a % 7 != 0)

Или просто напишите так, как вы это сказали:

   if (!(a % 3 == 0 && a % 7 == 0))

Ответ 5

Все, что вам действительно нужно:

if ((a%21) != 0) Console.WriteLine(a);

Объяснение: Числа, которые делятся как на a, так и на b, по существу являются числами, делящимися LCM a и b. Так как 3 и 7 являются простым числом, вы в основном ищете числа, которые не делятся на 3 * 7.

Ответ 6

Люди написали эссе в ответ на этот вопрос, не обращаясь к делу.

Просто взглянув на условное выражение Таблица истинности, вы можете видеть, что если

 X(NOT multiple of 3) Y(NOT multiple of 7)   X && Y
      true                   true            'a' printed as it is not a multiple of either
      true                   false           'a' not printed, it is multiple of 7
      false                  true            'a' not printed, it is multiple of 3
      false                  false           'a' not printed, it is multiple of both 

Вот почему все кратные 3 или 7 или 21 не печатаются.


Что вы хотите: Числа, которые

  • не a (кратно 3 AND 7). И это
  • ! (a% 3 == 0 & a% 7 == 0) или еще более упрощен до
  • ! (a% 21 == 0) или даже
  • (a% 21!= 0)

Ответ 7

a % b != 0 означает, что "a не делится на b".

Если что-то не делится на 3 и не делится на 7, оно делится на ни. Таким образом, если оно кратно 3 или, кратное 7, ваше утверждение будет ложным.

Часто помогает думать о логике с точки зрения реальных вещей:
(имейте в виду, что true and false == false и true or false == true)

Океан синий (а делится на 3).
Океан не желтый (а не делится на 7).

Что у вас есть:
Океан не голубой, а океан не желтый - это ложь (вы хотите, чтобы это было правдой).

Что вы хотите:
Океан не (синий и желтый) - это правда (океан синий, не синий и желтый).
Океан не голубой или океан не желтый - это правда (океан не желтый).

Эквивалент последних двух операторов:

!(a % 3 == 0 && a % 7 == 0)
(a % 3 != 0 || a % 7 != 0)

И вы можете конвертировать один в другой с помощью законов Де Моргана.

Ответ 8

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

Вы хотите "напечатать все числа от 1 до N (ввод пользователя), за исключением тех, которые делятся на 3 и 7 одновременно". Старые таймеры могут быстро выплевывать правильную и эффективную реализацию с использованием логических операторов. Как новичок, вы можете обнаружить, что это помогает разбить его на части.

// write out the highest level problem to solve, using functions as
// placeholders for part of the algorithm you don't immediately know
// how to solve
for ($x = 1; $x <= $N; $x++) {
    if (is_not_divisible_by_3_and_7($x)) {
        print "$x\n";
    }
}

// then think about the function placeholders, writing them out using
// (again) function placeholders for things you don't immediately know
// how to do
function is_not_divisible_by_3_and_7($number) {
    if (is_divisible_by_3_and_7($number)) {
        return false;
    } else {
        return true;
    }
}

// keep repeating this...
function is_divisible_by_3_and_7($number) {
    if (is_divisible_by_3($number) && is_divisible_by_7($number)) {
        return true;
    } else {
        return false;
    }
}

// until you have the simplest possible functions
function is_divisible_by_3($number) {
    if ($number % 3 === 0) {
        return true;
    } else {
        return false;
    }
}

function is_divisible_by_7($number) {
    if ($number % 7 === 0) {
        return true;
    } else {
        return false;
    }
}

Это проще, потому что каждая функция выполняет одну вещь, а имя функции описывает именно эту вещь. Это также удовлетворяет первому правилу программирования: сначала должен быть правильный код.

Затем вы можете начать думать о том, чтобы сделать код лучше,, где лучше может означать:

  • меньше строк кода
  • меньше вычислений
  • больше комментариев

Используя этот подход с приведенным выше кодом, очевидным улучшением является замена is_divisible_by_3 и is_divisible_by_7 на общую функцию:

function is_divisible_by_n($number, $divisor) {
    if ($number % $divisor === 0) {
        return true;
    } else {
        return false;
    }
}

Затем вы можете заменить все большие, громоздкие if x return true else return false тройным оператором, который позволит вам:

function is_divisible_by_n($number, $divisor) {
    return ($number % $divisor === 0) ? true : false;
}

function is_divisible_by_3_and_7($number) {
    return (is_divisible_by_n($number, 3) && is_divisible_by_n($number, 7)) ? true : false;
}

function is_not_divisible_by_3_and_7($number) {
    return (is_divisible_by_3_and_7($number)) ? false : true;
}

Теперь обратите внимание, что is_not_divisible_by_3_and_7 выглядит точно так же, как is_divisible_by_3_and_7, за исключением того, что возвраты переключаются, поэтому вы можете свернуть их одним способом:

function is_not_divisible_by_3_and_7($number) {
    // look how it changed here ----------------------------------------------VVVVV - VVVV
    return (is_divisible_by_n($number, 3) && is_divisible_by_n($number, 7)) ? false : true;
}

Теперь, вместо использования тройных операторов, вы можете использовать тот факт, что сами сравнения возвращают значение:

function is_divisible_by_n($number, $divisor) {
    // this expression returns a "truthy" value: true or false
    //     vvvvvvvvvvvvvvvvvvvvvvvvvv
    return ($number % $divisor === 0);
}

function is_not_divisible_by_3_and_7($number) {
    // also returns a truthy value, but inverted because of the !
    //    vvv
    return ! (is_divisible_by_n($number, 3) && is_divisible_by_n($number, 7));
}

Наконец, вы можете просто механически заменить вызовы функций эквивалентными логическими операциями:

for ($x = 1; $x <= $N; $x++) {
    // all I did below was copy from the function, replace variable names
    //  v  vvvvvvvvvvvvvv    vvvvvvvvvvvvvv
    if (! (($x % 3 === 0) && ($x % 7 === 0))) {
        print "$x\n";
    }
}

В качестве бонусных очков вы можете применить правило DeMorgan, чтобы распределить не через выражение:

for ($x = 1; $x <= $N; $x++) {
    if ($x % 3 !== 0 || $x % 7 !== 0) {
        print "$x\n";
    }
}

Кроме того, вы можете заметить, что два взаимно простых числа имеют общие коэффициенты тогда и только тогда, когда они имеют общий коэффициент N раз M, поэтому:

for ($x = 1; $x <= $N; $x++) {
    if ($x % (3*7) !== 0) {
        print "$x\n";
    }
}

Вы можете сделать это дальше, используя свои языковые функции, чтобы сжать выражение больше:

array_walk(
    range(1, $N),
    function ($x) {
        if ($x % 21 !== 0) print "$x\n";
    }
);

И так далее. Дело в том, что вы начинаете с правильного написания кода, затем вы делаете это лучше. Иногда создание правильного кода означает долгое и долгое мышление. Иногда это просто означает запись его очень маленькими, очень явными шагами.

Ответ 9

& & ведет себя иначе, чем ||

Чтобы понять разницу, это может помочь сделать некоторые тесты с более простыми выражениями:

if (true && false)
if (true || false)

Итак, ваша проблема заключается в понимании других операторов в вашем коде (!= и%).

Это часто помогает разделить условия на более мелкие выражения с пояснениями:

bool divisbleBy3 = (a % 3 == 0);
bool divisbleBy7 = (a % 7 == 0);

if (divisbleBy3 && divisibleBy7)
{
    // do not print
}
else
{
    // print
}

Ответ 10

Очевидно, && и || разные.

В нем говорится: if (true && false) = false if (true || false) = true