usar usa unario ternarios que para operadores operador entre diferencia como asignacion amp c# .net logic

c# - usa - El operador de && se comporta como || operador



operadores ternarios c# (10)

Soy un principiante y he estado tratando de ejecutar un programa que imprime todos los números del 1 al N (entrada del usuario), excepto aquellos que son divisibles entre 3 y 7 al mismo tiempo. Sin embargo, lo que hace mi código, en cambio, es que imprime los números del 1 al N, excepto los divisibles entre 3 o 7. Lo examiné por un tiempo y no tengo idea de por qué lo hace. Por favor, explícame en qué me equivoco.

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(); }

Cuando invierto los signos de la sentencia if para == el operador && funciona correctamente, pero si el signo es != Simplemente actúa como un || Operador, por lo que me confunde aún más. El problema es más probable en la condición, pero no puedo ver qué es lo que está mal.


&& se comporta de manera diferente a ||

Para entender la diferencia, puede ayudar hacer algunas pruebas con expresiones más simples:

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

Entonces, su problema es entender a los otros operadores en su código (! = Y%).

A menudo ayuda dividir las condiciones en expresiones más pequeñas, con explicaciones:

bool divisbleBy3 = (a % 3 == 0); bool divisbleBy7 = (a % 7 == 0); if (divisbleBy3 && divisibleBy7) { // do not print } else { // print }


Deberías leer las leyes de De Morgan.

"no (A y B)" es lo mismo que "(no A) o (no B)"

además,

"no (A o B)" es lo mismo que "(no A) y (no B)".

a % 3 != 0 && a % 7 != 0 es verdadero cuando a no es divisible por 3 ( a % 3 != 0 ) y no es divisible por 7 ( a % 7 != 0 ). Entonces, todos los a que son divisibles por 3 o 7 (3,6,7,9,12,14,...) hacen que toda la expresión sea falsa. Puede reformularlo como !(a % 3 == 0 || a % 7 == 0)


Debiera ser:

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

Significa exactamente: todos los números, excepto aquellos que son divisibles entre 3 y 7 al mismo tiempo.

También puedes reformularlo como:

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


Mirando la tabla de verdad de su declaración condicional, puede ver que si

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

Es por eso que no se imprimen todos los múltiplos de 3 o 7 o 21.

Lo que quieres: Números, que son.

  • No es un (múltiplo de 3 y 7) . Y eso es
  • ! (a% 3 == 0 && a% 7 == 0) o incluso más simplificado a
  • ! (a% 21 == 0) o incluso
  • (a% 21! = 0)

Obviamente && y || son diferentes.

Indica: si (verdadero y falso) = falso si (verdadero || falso) = verdadero


Que dijiste:

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

Que escribiste:

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

No es lo mismo. Aristóteles lo pensó primero, Augustus De Morgan escribió las leyes hace 158 años, aplica el operador no a los operandos e invierte la operación lógica:

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

Lo que produce:

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

O simplemente escríbelo como lo dijiste:

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


Todo lo que necesitas es:

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

Explicación: Los números que son divisibles por a y b son esencialmente los números divisibles por el MCM de a y b. Como 3 y 7 son números primos, básicamente estás buscando números que no sean divisibles entre 3 * 7.


a % b != 0 significa que "a no es divisible por b".

Si algo no es divisible por 3 y no es divisible por 7, no es divisible por ninguno . Por lo tanto, si es un múltiplo de 3 o un múltiplo de 7, su declaración será falsa.

A menudo ayuda pensar la lógica en términos de cosas del mundo real:
(tenga en cuenta que true and false == false y true or false == true )

El océano es azul (a es divisible por 3).
El océano no es amarillo (a no es divisible por 7).

Que tienes:
El océano no es azul y el océano no es amarillo; esto es falso (quieres que esto sea cierto).

Lo que quieras:
El océano no es (azul y amarillo); esto es cierto (el océano es solo azul, no azul y amarillo).
El océano no es azul o el océano no es amarillo, esto es cierto (el océano no es amarillo).

El equivalente de las 2 últimas declaraciones sería:

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

Y puedes convertir uno a otro usando las leyes de De Morgan .


"Excepto los números que son divisibles entre 3 y 7 al mismo tiempo" se pueden dividir de la siguiente manera:

"divisible by 3 and 7 at the same time" se puede expresar como:

"(divisible by 3 and divisible by 7)"

"Except" se puede expresar como "Not" .

Así que tienes:

Not (divisible by 3 and divisible by 7)

"divisible por 3" es (a % 3) == 0

"divisible por 7" es (a % 7) == 0

Dando:

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

En C # Not convierte ! y and convierte en && , para que puedas escribir todo en C # como:

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

Compare con su incorrecto:

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

Este último es incorrecto porque significa:

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

es decir, significa "Print the number if it is neither divisible by 3 nor divisible by 7" , lo que significa "don''t print the number if it''s divisible by 3 or 7" .

Para ver por qué, primero considere el número 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)

Entonces, esto se resuelve en if false and true cual es, por supuesto, false .

Este resultado también se aplica a cualquier otro número divisible por 3, por lo que no se imprimirán números divisibles por 3.

Ahora considera el número 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)

Entonces, esto se resuelve if true and false cual es, por supuesto, false .

Este resultado también se aplica a cualquier otro número divisible por 7, por lo que no se imprimirán números divisibles por 7.

Esperemos que puedas ver por qué está mal ahora. Si no, considere este ejemplo equivalente:

Supongamos que tenemos cuatro personas, Tom el carpintero, Dick el carpintero, Harry el carnicero y Tom el carnicero.

Esta pregunta es equivalente a la que estás preguntando:

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

Y deberías poder ver que esto es lo mismo que preguntar:

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

En ambos casos, la respuesta es Dick el carpintero.

La pregunta que deberías haber hecho es:

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

A lo que la respuesta es Tom el Carpintero, Dick el Carpintero y Harry el Carnicero.

Nota : Las leyes de De Morgan.

La segunda ley establece que:

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

Este es el equivalente de mi ejemplo anterior donde:

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

es el equivalente a:

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

donde A es anyone called Tom y B es anyone who is a butcher y not está escrito como except .


Si no sabe cómo implementar un algoritmo, intente dividirlo en funciones obviamente correctas que cada uno implemente como parte del algoritmo.

Desea "imprimir todos los números del 1 al N (entrada del usuario) excepto los que son divisibles entre 3 y 7 al mismo tiempo". Los temporizadores antiguos pueden escupir rápidamente una implementación correcta y eficiente utilizando operadores lógicos. Como principiante, puede que te resulte útil dividirlo en pedazos.

// 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; } }

Esto es más fácil de seguir, porque cada función hace una cosa y el nombre de la función describe exactamente esa cosa. Esto también satisface la primera regla de programación: el código correcto es lo primero .

Entonces puede comenzar a pensar en mejorar el código, donde mejor puede significar:

  • menos líneas de código
  • menos cálculos
  • Más comentarios

Tomando este enfoque con el código anterior, una mejora obvia es reemplazar is_divisible_by_3 y is_divisible_by_7 con una función genérica:

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

A continuación, puede reemplazar todo lo grande y voluminoso if x return true else return false con el operador ternario, lo que le permite:

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; }

Ahora, observe que is_not_divisible_by_3_and_7 ve exactamente como is_divisible_by_3_and_7 , excepto que los retornos se cambian, por lo que puede contraerlos en un solo método:

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; }

Ahora, en lugar de utilizar operadores ternarios, puede aprovechar el hecho de que las comparaciones devuelven un valor:

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)); }

Finalmente, simplemente puede reemplazar mecánicamente las llamadas de función con sus operaciones lógicas equivalentes:

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"; } }

Como puntos de bonificación, puede aplicar la regla de DeMorgan, para distribuir el no a través de la expresión:

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

Además, puede observar que dos números primarios tienen factores comunes si y solo si tienen el factor común N veces M, así que:

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

Puede llevar esto más lejos utilizando las funciones de su idioma para compactar más la expresión:

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

Y así. El punto es que comienzas haciendo que tu código sea correcto, luego lo haces mejor. A veces, hacer que el código sea correcto significa pensar largo y duro. A veces solo significa escribirlo en pasos muy pequeños y muy explícitos.