& el & operador se comporta como / / operador


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 por 3 y 7 al mismo tiempo. Lo que mi código hace en su lugar, sin embargo, es que imprime los números de 1 a N, excepto aquellos que son divisibles por 3 o 7. Lo examiné por un tiempo y no tengo idea de por qué lo hace. Por favor, explícame en qué me estoy equivocando.

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 declaración if a == el && operator 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 muy probable en la condición, pero no puedo ver lo que está mal con él.

Author: Hamid Pourjam, 2015-09-10

10 answers

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

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

"(divisible by 3 and divisible by 7)"

"Except" puede expresarse como "Not".

Así que obtienes:

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 se convierte en ! y and se convierte en &&, así que puedes escribir todo en C# as:

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


Compare con su incorrecto:

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

Esto último es incorrecto porque significa:{[36]]}

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", 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:{[36]]}

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)

Así que esto se resuelve a if false and true que 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 consideremos 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)

Así que esto se resuelve a if true and false que 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.

Espero 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 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: {[36]]}

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: {[36]]}

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

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


Nota de pie de página: De Morgan's laws

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 se escribe como except.

 95
Author: Matthew Watson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-10 21:26:16

Deberías leer Las leyes de De Morgan

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

También,

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

a % 3 != 0 && a % 7 != 0 es cierto cuando a no es divisible por 3 (a % 3 != 0) y no divisible por 7 (a % 7 != 0). Así que todos los as que son divisibles por 3 o 7 (3,6,7,9,12,14,...) hace que toda la expresión es false. Puedes reformularlo como !(a % 3 == 0 || a % 7 == 0)

 73
Author: Hamid Pourjam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-11 00:11:45

Todo lo que realmente necesitas es:

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

Explicación: Los números que son divisibles por a y b {[8] } son esencialmente los números divisibles por el LCM de a y b. Dado que 3 y 7 son números primos, básicamente estás buscando números que no sean divisibles por 3*7.

 9
Author: displayName,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-10 20:18:43

Debe ser:

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

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

También podrías reformularlo como:

if ( a % 3 != 0 || a % 7 != 0 )
{
    Console.WriteLine(a);
}
 9
Author: user2622016,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-11 00:12:01

Lo que dijiste:

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

Lo que escribiste:

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

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

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

Que produce:

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

O simplemente escríbelo como lo dijiste:

   if (!(a % 3 == 0 && a % 7 == 0))
 9
Author: Hans Passant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-09 13:20:03

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 a (múltiplo de 3 Y 7). Y eso es
  • !(a % 3 = = 0 & & a%7==0) o incluso simplificada a
  • !(a%21 == 0) o incluso
  • (un%21 != 0)
 5
Author: displayName,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-11 15:10:42

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

Si algo no es divisible por 3 y no divisible por 7, es divisible por ni. 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 en 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).

Lo que tienes:
El océano no es azul y el océano no es amarillo - esto es falso (quieres que esto sea verdad).

Lo que quieres:
El océano no es (azul y amarillo) - esto es cierto (el océano es solo azul, no tanto azul como 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 últimas 2 declaraciones sería:

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

Y puede convertir uno a la otros usando Las leyes de De Morgan.

 4
Author: Dukeling,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-10 13:01:44

Si no sabes cómo implementar un algoritmo, intenta dividirlo en funciones obviamente correctas que cada implementa parte del algoritmo.

Desea "imprimir todos los números del 1 al N (entrada del usuario) excepto aquellos que son divisibles por 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 encontrar que ayuda a descomponerlo en pieza.

// 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 viene primero.

Entonces puedes empezar a pensar en hacer el código mejor, 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 todos los grandes y voluminosos if x return true else return false con el operador ternario, lo que le lleva a:

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 se ve exactamente igual que is_divisible_by_3_and_7, excepto que los retornos son cambiados, por lo que puede colapsarlos en un 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 usar operadores ternarios, puede aprovechar el hecho de que las comparaciones mismas 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 a la 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 not 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 coprimos tienen factores comunes si y solo si tienen un factor común N por 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 características de su lenguaje para compactar la expresión más:

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

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

 1
Author: bishop,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-09 13:44:43

& & 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)

Por lo tanto, su problema es con la comprensión de 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
}
 0
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-10 13:01:06

, Obviamente, & & y || son diferentes.

Establece: if (true && false) = false if (true / / false) = true

 -1
Author: Priyanka,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-06 06:50:19