2012-07-25 12 views
13

Estoy tratando de verificar que una variable NO es igual a esto o aquello. Intenté usar los siguientes códigos, pero ninguno funciona:No es igual a este O que en Lua

if x ~=(0 or 1) then 
    print("X must be equal to 1 or 0") 
    return 
end 


if x ~= 0 or 1 then 
    print("X must be equal to 1 or 0") 
    return 
end 

¿Hay alguna manera de hacerlo?

Respuesta

37

Su problema se deriva de una mala interpretación del operador or que es común a personas que están aprendiendo lenguajes de programación como esta. Sí, su problema inmediato se puede resolver escribiendo x ~= 0 and x ~= 1, pero voy a entrar en más detalles sobre por qué su intento de solución no funciona.

Cuando lee x ~=(0 or 1) o x ~= 0 or 1 es natural analizar esto como lo haría con la oración "x no es igual a cero o uno". En la comprensión ordinaria de esa afirmación, "x" es el sujeto, "no es igual a" es el predicado o frase verbal, y "cero o uno" es el objeto, un conjunto de posibilidades unidas por una conjunción. Aplica el sujeto con el verbo a cada elemento del conjunto.

Sin embargo, Lua no analiza esto basándose en las reglas de la gramática inglesa, sino que lo analiza en comparaciones binarias de dos elementos en función de su orden de operaciones. Cada operador tiene un precedence que determina el orden en que se evaluará. or tiene una precedencia menor que ~=, al igual que la suma en matemáticas tiene una precedencia menor que la multiplicación. Todo tiene una precedencia menor que paréntesis.

Como resultado, al evaluar x ~=(0 or 1), el intérprete primero calcular 0 or 1 (a causa de los paréntesis) y luego x ~= el resultado de la primera computación, y en el segundo ejemplo, se calculará x ~= 0 y luego aplicar el resultado de ese cálculo a or 1.

"logical operator or" devuelve su primer argumento si este valor es diferente de cero y falso; de lo contrario, o devuelve su segundo argumento ". El relational operator ~= es el inverso del operador de igualdad ==; devuelve verdadero si sus argumentos son de tipos diferentes (x es un número, ¿no?), y de lo contrario compara sus argumentos normalmente.

El uso de estas reglas, x ~=(0 or 1) se descompondrá a x ~= 0 (después de aplicar el operador or) y esto devolverá 'verdadero' si x es otra cosa que no sea 0, incluyendo 1, que es indeseable. La otra forma, x ~= 0 or 1 primero evaluará x ~= 0 (que puede devolver verdadero o falso, dependiendo del valor de x).Luego, se descompondrá en uno de false or 1 o true or 1. En el primer caso, la declaración devolverá 1, y en el segundo caso, la declaración devolverá true. Debido a que las estructuras de control en Lua solo consideran que nil y false son falsos, y cualquier otra cosa es cierta, esto siempre ingresará la declaración if, que tampoco es lo que usted desea.

No hay manera de que pueda usar operadores binarios como los provistos en los lenguajes de programación para comparar una sola variable con una lista de valores. En cambio, debe comparar la variable con cada valor uno por uno. Hay algunas maneras de hacer esto. La forma más simple es usar De Morgan's laws para expresar la declaración 'no uno o cero' (que no se puede evaluar con operadores binarios) como 'no uno y no cero', que se puede escribir trivialmente con operadores binarios:

if x ~= 1 and x ~= 0 then 
    print("X must be equal to 1 or 0") 
    return 
end 

Como alternativa, puede utilizar un bucle para comprobar estos valores:

local x_is_ok = false 
for i = 0,1 do 
    if x == i then 
     x_is_ok = true 
    end 
end 
if not x_is_ok then 
    print("X must be equal to 1 or 0") 
    return 
end 

por último, se puede utilizar operadores relacionales para comprobar una serie y luego probar que x era un entero en el rango (que no quiere 0.5, ¿verdad?)

if not (x >= 0 and x <= 1 and math.floor(x) == x) then 
    print("X must be equal to 1 or 0") 
    return 
end 

Tenga en cuenta que escribí x >= 0 and x <= 1. Si entendiste la explicación anterior, ahora deberías ser capaz de explicar por qué no escribí 0 <= x <= 1, ¡y qué devolvería esta expresión errónea!

+0

¡Gracias, eso lo explica perfectamente! – Ian

+2

Debería enseñar clases de programación si aún no lo hace. :) – spirulence

+1

No sé mucho sobre Lua, pero tal vez deberías mencionar que también se puede usar 'if not (x == 1 or x == 0) then', en conexión con tu mención de la ley de De Morgan. –

8

Para ensayo sólo dos valores, yo personalmente hago esto:

if x ~= 0 and x ~= 1 then 
    print("X must be equal to 1 or 0") 
    return 
end 

Si necesita probar contra más de dos valores, me meto sus opciones en una tabla de actuar como un conjunto, como así:

choices = {[0]=true, [1]=true, [3]=true, [5]=true, [7]=true, [11]=true} 

if not choices[x] then 
    print("x must be in the first six prime numbers") 
    return 
end 
3

x ~= 0 or 1 es la misma que ((x ~= 0) or 1)

x ~=(0 or 1) es el mismo que (x ~= 0).

intente algo como esto en su lugar.

function isNot0Or1(x) 
    return (x ~= 0 and x ~= 1) 
end 

print(isNot0Or1(-1) == true) 
print(isNot0Or1(0) == false) 
print(isNot0Or1(1) == false) 
Cuestiones relacionadas