Оператор && ведет себя как || оператор
Я начинаю, и я пытаюсь запустить программу, которая печатает все числа от 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 на ==
, оператор &&
работает правильно, но если знак !=
, он просто действует как оператор ||
, так что меня еще больше смущает. Проблема, скорее всего, в состоянии, но я не вижу, что с ней не так.
Ответы
Ответ 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