operadores metodo logicos ejemplos ejemplo declarar con comparar java boolean boolean-logic

logicos - metodo boolean java



Comprueba si al menos dos de cada tres booleanos son verdaderos (30)

¿Por qué no implementarlo literalmente? :)

(a?1:0)+(b?1:0)+(c?1:0) >= 2

En C, simplemente puedes escribir a+b+c >= 2 (o !!a+!!b+!!c >= 2 para ser muy seguro).

En respuesta a la comparación de TofuBeer del código de bytes de Java, aquí hay una prueba de rendimiento simple:

class Main { static boolean majorityDEAD(boolean a,boolean b,boolean c) { return a; } static boolean majority1(boolean a,boolean b,boolean c) { return a&&b || b&&c || a&&c; } static boolean majority2(boolean a,boolean b,boolean c) { return a ? b||c : b&&c; } static boolean majority3(boolean a,boolean b,boolean c) { return a&b | b&c | c&a; } static boolean majority4(boolean a,boolean b,boolean c) { return (a?1:0)+(b?1:0)+(c?1:0) >= 2; } static int loop1(boolean[] data, int i, int sz1, int sz2) { int sum = 0; for(int j=i;j<i+sz1;j++) { for(int k=j;k<j+sz2;k++) { sum += majority1(data[i], data[j], data[k])?1:0; sum += majority1(data[i], data[k], data[j])?1:0; sum += majority1(data[j], data[k], data[i])?1:0; sum += majority1(data[j], data[i], data[k])?1:0; sum += majority1(data[k], data[i], data[j])?1:0; sum += majority1(data[k], data[j], data[i])?1:0; } } return sum; } static int loop2(boolean[] data, int i, int sz1, int sz2) { int sum = 0; for(int j=i;j<i+sz1;j++) { for(int k=j;k<j+sz2;k++) { sum += majority2(data[i], data[j], data[k])?1:0; sum += majority2(data[i], data[k], data[j])?1:0; sum += majority2(data[j], data[k], data[i])?1:0; sum += majority2(data[j], data[i], data[k])?1:0; sum += majority2(data[k], data[i], data[j])?1:0; sum += majority2(data[k], data[j], data[i])?1:0; } } return sum; } static int loop3(boolean[] data, int i, int sz1, int sz2) { int sum = 0; for(int j=i;j<i+sz1;j++) { for(int k=j;k<j+sz2;k++) { sum += majority3(data[i], data[j], data[k])?1:0; sum += majority3(data[i], data[k], data[j])?1:0; sum += majority3(data[j], data[k], data[i])?1:0; sum += majority3(data[j], data[i], data[k])?1:0; sum += majority3(data[k], data[i], data[j])?1:0; sum += majority3(data[k], data[j], data[i])?1:0; } } return sum; } static int loop4(boolean[] data, int i, int sz1, int sz2) { int sum = 0; for(int j=i;j<i+sz1;j++) { for(int k=j;k<j+sz2;k++) { sum += majority4(data[i], data[j], data[k])?1:0; sum += majority4(data[i], data[k], data[j])?1:0; sum += majority4(data[j], data[k], data[i])?1:0; sum += majority4(data[j], data[i], data[k])?1:0; sum += majority4(data[k], data[i], data[j])?1:0; sum += majority4(data[k], data[j], data[i])?1:0; } } return sum; } static int loopDEAD(boolean[] data, int i, int sz1, int sz2) { int sum = 0; for(int j=i;j<i+sz1;j++) { for(int k=j;k<j+sz2;k++) { sum += majorityDEAD(data[i], data[j], data[k])?1:0; sum += majorityDEAD(data[i], data[k], data[j])?1:0; sum += majorityDEAD(data[j], data[k], data[i])?1:0; sum += majorityDEAD(data[j], data[i], data[k])?1:0; sum += majorityDEAD(data[k], data[i], data[j])?1:0; sum += majorityDEAD(data[k], data[j], data[i])?1:0; } } return sum; } static void work() { boolean [] data = new boolean [10000]; java.util.Random r = new java.util.Random(0); for(int i=0;i<data.length;i++) data[i] = r.nextInt(2) > 0; long t0,t1,t2,t3,t4,tDEAD; int sz1 = 100; int sz2 = 100; int sum = 0; t0 = System.currentTimeMillis(); for(int i=0;i<data.length-sz1-sz2;i++) sum += loop1(data, i, sz1, sz2); t1 = System.currentTimeMillis(); for(int i=0;i<data.length-sz1-sz2;i++) sum += loop2(data, i, sz1, sz2); t2 = System.currentTimeMillis(); for(int i=0;i<data.length-sz1-sz2;i++) sum += loop3(data, i, sz1, sz2); t3 = System.currentTimeMillis(); for(int i=0;i<data.length-sz1-sz2;i++) sum += loop4(data, i, sz1, sz2); t4 = System.currentTimeMillis(); for(int i=0;i<data.length-sz1-sz2;i++) sum += loopDEAD(data, i, sz1, sz2); tDEAD = System.currentTimeMillis(); System.out.println("a&&b || b&&c || a&&c : " + (t1-t0) + " ms"); System.out.println(" a ? b||c : b&&c : " + (t2-t1) + " ms"); System.out.println(" a&b | b&c | c&a : " + (t3-t2) + " ms"); System.out.println(" a + b + c >= 2 : " + (t4-t3) + " ms"); System.out.println(" DEAD : " + (tDEAD-t4) + " ms"); System.out.println("sum: "+sum); } public static void main(String[] args) throws InterruptedException { while(true) { work(); Thread.sleep(1000); } } }

Esto imprime lo siguiente en mi máquina (ejecutando Ubuntu en Intel Core 2 + sun java 1.6.0_15-b03 con HotSpot Server VM (14.1-b02, modo mixto)):

Primera y segunda iteraciones:

a&&b || b&&c || a&&c : 1740 ms a ? b||c : b&&c : 1690 ms a&b | b&c | c&a : 835 ms a + b + c >= 2 : 348 ms DEAD : 169 ms sum: 1472612418

Iteraciones posteriores:

a&&b || b&&c || a&&c : 1638 ms a ? b||c : b&&c : 1612 ms a&b | b&c | c&a : 779 ms a + b + c >= 2 : 905 ms DEAD : 221 ms

Me pregunto, ¿qué podría hacer Java VM que degrada el rendimiento con el tiempo para (a + b + c> = 2) caso.

Y esto es lo que sucede si ejecuto java con un -client VM de -client :

a&&b || b&&c || a&&c : 4034 ms a ? b||c : b&&c : 2215 ms a&b | b&c | c&a : 1347 ms a + b + c >= 2 : 6589 ms DEAD : 1016 ms

Misterio...

Y si lo ejecuto en GNU Java Interpreter , se vuelve casi 100 veces más lento, pero a&&b || b&&c || a&&c a&&b || b&&c || a&&c a&&b || b&&c || a&&c versión de a&&b || b&&c || a&&c gana entonces.

Resultados de Tofubeer con el último código que ejecuta OS X:

a&&b || b&&c || a&&c : 1358 ms a ? b||c : b&&c : 1187 ms a&b | b&c | c&a : 410 ms a + b + c >= 2 : 602 ms DEAD : 161 ms

Resultados de Paul Wagland con una Mac Java 1.6.0_26-b03-383-11A511

a&&b || b&&c || a&&c : 394 ms a ? b||c : b&&c : 435 ms a&b | b&c | c&a : 420 ms a + b + c >= 2 : 640 ms a ^ b ? c : a : 571 ms a != b ? c : a : 487 ms DEAD : 170 ms

Un entrevistador recientemente me hizo esta pregunta: dadas tres variables booleanas, a, b, yc, devuelve verdadero si al menos dos de los tres son verdaderos

Mi solución sigue:

boolean atLeastTwo(boolean a, boolean b, boolean c) { if ((a && b) || (b && c) || (a && c)) { return true; } else{ return false; } }

Dijo que esto se puede mejorar aún más, pero ¿cómo?


Añádelo. Se llama álgebra booleana por una razón:

0 x 0 = 0 1 x 0 = 0 1 x 1 = 1 0 + 0 = 0 1 + 0 = 1 1 + 1 = 0 (+ carry)

Si miras las tablas de verdad allí, puedes ver que la multiplicación es booleana y, simplemente, la suma es xor.

Para responder tu pregunta:

return (a + b + c) >= 2


Aquí hay otra implementación usando map / reduce. Esto se adapta bien a miles de millones de booleanos © en un entorno distribuido. Utilizando MongoDB:

Creando una base de datos de values booleanos:

db.values.insert({value: true}); db.values.insert({value: false}); db.values.insert({value: true});

Creando el mapa, reducir funciones:

Edición : Me gusta CurtainDog answer CurtainDog acerca de que map / reduce se aplique a listas genéricas, por lo que aquí va una función de mapa que toma una devolución de llamada que determina si un valor debe contarse o no.

var mapper = function(shouldInclude) { return function() { emit(null, shouldInclude(this) ? 1 : 0); }; } var reducer = function(key, values) { var sum = 0; for(var i = 0; i < values.length; i++) { sum += values[i]; } return sum; }

Mapa de ejecución / reducir:

var result = db.values.mapReduce(mapper(isTrue), reducer).result; containsMinimum(2, result); // true containsMinimum(1, result); // false function isTrue(object) { return object.value == true; } function containsMinimum(count, resultDoc) { var record = db[resultDoc].find().next(); return record.value >= count; }


Aquí hay un enfoque general basado en pruebas. No es tan "eficiente" como la mayoría de las soluciones ofrecidas hasta ahora, pero es claro, probado, funcional y generalizado.

public class CountBooleansTest extends TestCase { public void testThreeFalse() throws Exception { assertFalse(atLeastTwoOutOfThree(false, false, false)); } public void testThreeTrue() throws Exception { assertTrue(atLeastTwoOutOfThree(true, true, true)); } public void testOnes() throws Exception { assertFalse(atLeastTwoOutOfThree(true, false, false)); assertFalse(atLeastTwoOutOfThree(false, true, false)); assertFalse(atLeastTwoOutOfThree(false, false, true)); } public void testTwos() throws Exception { assertTrue(atLeastTwoOutOfThree(false, true, true)); assertTrue(atLeastTwoOutOfThree(true, false, true)); assertTrue(atLeastTwoOutOfThree(true, true, false)); } private static boolean atLeastTwoOutOfThree(boolean b, boolean c, boolean d) { return countBooleans(b, c, d) >= 2; } private static int countBooleans(boolean... bs) { int count = 0; for (boolean b : bs) if (b) count++; return count; } }


En Clojure :

(defn at-least [n & bools] (>= (count (filter true? bools)) n)

Uso:

(at-least 2 true false true)


En lugar de escribir:

if (someExpression) { return true; } else { return false; }

Escribir:

return someExpression;

En cuanto a la expresión en sí, algo como esto:

boolean atLeastTwo(boolean a, boolean b, boolean c) { return a ? (b || c) : (b && c); }

o esto (lo que encuentre más fácil de entender):

boolean atLeastTwo(boolean a, boolean b, boolean c) { return a && (b || c) || (b && c); }

Prueba a y b exactamente una vez, c como máximo una vez.

Referencias


Este tipo de preguntas se pueden resolver con un Mapa de Karnaugh :

| C | !C ------|---|---- A B | 1 | 1 A !B | 1 | 0 !A !B | 0 | 0 !A B | 1 | 0

de lo que deduce que necesita un grupo para la primera fila y dos grupos para la primera columna, obteniendo la solución óptima de poligénelubricantes:

(C && (A || B)) || (A && B) <---- first row ^ | first column without third case


La legibilidad debe ser el objetivo. Alguien que lea el código debe entender su intención de inmediato. Así que aquí está mi solución.

int howManyBooleansAreTrue = (a ? 1 : 0) + (b ? 1 : 0) + (c ? 1 : 0); return howManyBooleansAreTrue >= 2;


Las mejoras más obvias son:

// There is no point in an else if you already returned. boolean atLeastTwo(boolean a, boolean b, boolean c) { if ((a && b) || (b && c) || (a && c)) { return true; } return false; }

y entonces

// There is no point in an if(true) return true otherwise return false. boolean atLeastTwo(boolean a, boolean b, boolean c) { return ((a && b) || (b && c) || (a && c)); }

Pero esas mejoras son menores.


No creo que haya visto esta solución todavía:

boolean atLeast(int howMany, boolean[] boolValues) { // check params for valid values int counter = 0; for (boolean b : boolValues) { if (b) { counter++; if (counter == howMany) { return true; } } } return false; }

Su ventaja es que una vez que alcanza el número que estás buscando, se rompe. Entonces, si esto fue "al menos 2 de estos 1,000,000 valores son verdaderos" donde los dos primeros son realmente verdaderos, entonces debería ir más rápido que algunas de las soluciones más "normales".


No es necesario utilizar las formas de cortocircuito de los operadores.

return (a & b) | (b & c) | (c & a);

Esto realiza el mismo número de operaciones lógicas que su versión, sin embargo, no tiene sucursales.


No me gusta el ternario ( return a ? (b || c) : (b && c); de la respuesta superior), y no creo que haya visto a nadie mencionarlo. Está escrito así:

boolean atLeastTwo(boolean a, boolean b, boolean c) { if (a) { return b||c; } else { return b&&C; }


Otra forma de hacer esto, pero no muy buena:

return (Boolean.valueOf(a).hashCode() + Boolean.valueOf(b).hashCode() + Boolean.valueOf(c).hashCode()) < 3705);

Los valores de código hash Boolean se fijan en 1231 para true y 1237 para false, por lo que igualmente podrían haber usado <= 3699


Otro ejemplo de código directo:

int n = 0; if (a) n++; if (b) n++; if (c) n++; return (n >= 2);

No es el código más conciso, obviamente.

Apéndice

Otra versión (ligeramente optimizada) de esto:

int n = -2; if (a) n++; if (b) n++; if (c) n++; return (n >= 0);

Esto podría ejecutarse un poco más rápido, suponiendo que la comparación con 0 utilizará un código más rápido (o quizás menos) que la comparación con 2.


Podemos convertir los bools en enteros y realizar esta sencilla comprobación:

(int(a) + int(b) + int(c)) >= 2


Realmente depende de lo que quieras decir con "mejorado":

Más claro?

boolean twoOrMoreAreTrue(boolean a, boolean b, boolean c) { return (a && b) || (a && c) || (b && c); }

Terser?

boolean moreThanTwo(boolean a, boolean b, boolean c) { return a == b ? a : c; }

¿Mas general?

boolean moreThanXTrue(int x, boolean[] bs) { int count = 0; for(boolean b : bs) { count += b ? 1 : 0; if(count > x) return true; } return false; }

¿Más escalable?

boolean moreThanXTrue(int x, boolean[] bs) { int count = 0; for(int i < 0; i < bs.length; i++) { count += bs[i] ? 1 : 0; if(count > x) return true; int needed = x - count; int remaining = bs.length - i; if(needed >= remaining) return false; } return false; }

¿Más rápido?

// Only profiling can answer this.

Cuál es "mejorado" depende en gran medida de la situación.


Solo por usar XOR para responder a un problema relativamente sencillo ...

return a ^ b ? c : a


Solución de ca.

int two(int a, int b, int c) { return !a + !b + !c < 2; }

o usted puede preferir:

int two(int a, int b, int c) { return !!a + !!b + !!c >= 2; }


Tomando las respuestas (hasta ahora) aquí:

public class X { static boolean a(final boolean a, final boolean b, final boolean c) { return ((a && b) || (b && c) || (a && c)); } static boolean b(final boolean a, final boolean b, final boolean c) { return a ? (b || c) : (b && c); } static boolean c(final boolean a, final boolean b, final boolean c) { return ((a & b) | (b & c) | (c & a)); } static boolean d(final boolean a, final boolean b, final boolean c) { return ((a?1:0)+(b?1:0)+(c?1:0) >= 2); } }

y ejecutándolos a través del decompilador (javap -c X> results.txt):

Compiled from "X.java" public class X extends java.lang.Object{ public X(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: return static boolean a(boolean, boolean, boolean); Code: 0: iload_0 1: ifeq 8 4: iload_1 5: ifne 24 8: iload_1 9: ifeq 16 12: iload_2 13: ifne 24 16: iload_0 17: ifeq 28 20: iload_2 21: ifeq 28 24: iconst_1 25: goto 29 28: iconst_0 29: ireturn static boolean b(boolean, boolean, boolean); Code: 0: iload_0 1: ifeq 20 4: iload_1 5: ifne 12 8: iload_2 9: ifeq 16 12: iconst_1 13: goto 33 16: iconst_0 17: goto 33 20: iload_1 21: ifeq 32 24: iload_2 25: ifeq 32 28: iconst_1 29: goto 33 32: iconst_0 33: ireturn static boolean c(boolean, boolean, boolean); Code: 0: iload_0 1: iload_1 2: iand 3: iload_1 4: iload_2 5: iand 6: ior 7: iload_2 8: iload_0 9: iand 10: ior 11: ireturn static boolean d(boolean, boolean, boolean); Code: 0: iload_0 1: ifeq 8 4: iconst_1 5: goto 9 8: iconst_0 9: iload_1 10: ifeq 17 13: iconst_1 14: goto 18 17: iconst_0 18: iadd 19: iload_2 20: ifeq 27 23: iconst_1 24: goto 28 27: iconst_0 28: iadd 29: iconst_2 30: if_icmplt 37 33: iconst_1 34: goto 38 37: iconst_0 38: ireturn }

Puedes ver que los?: Unos son ligeramente mejores que la versión corregida de tu original. El que es el mejor es el que evita la ramificación por completo. Eso es bueno desde el punto de vista de tener menos instrucciones (en la mayoría de los casos) y mejor para las partes de predicción de ramificación de la CPU, ya que una estimación errónea de la predicción de ramificación puede provocar un bloqueo de la CPU.

Yo diría que el más eficiente es el de Moonshadow en general. Utiliza la menor cantidad de instrucciones en promedio y reduce la posibilidad de que se detengan las tuberías en la CPU.

Para estar 100% seguro de que necesitaría averiguar el costo (en ciclos de CPU) para cada instrucción, que, desafortunadamente, no está disponible (tendría que buscar en la fuente de punto de acceso y luego las especificaciones de los proveedores de CPU por el momento) tomado para cada instrucción generada).

Vea la respuesta actualizada de Rotsor para un análisis del código en tiempo de ejecución.


Ya que no se especificó cómo debería mejorarse el código, me esforzaré por mejorar el código haciéndolo más divertido. Aquí está mi solución:

boolean atLeastTwo(boolean t, boolean f, boolean True) { boolean False = True; if ((t || f) && (True || False)) return "answer" != "42"; if (t && f) return !"France".contains("Paris"); if (False == True) return true == false; return Math.random() > 0.5; }

En caso de que alguien se pregunte si este código funciona, aquí hay una simplificación utilizando la misma lógica:

boolean atLeastTwo(boolean a, boolean b, boolean c) { if ((a || b) && (c)) return true; if (a && b) return true; if (true) return false; // The last line is a red herring, as it will never be reached: return Math.random() > 0.5;

}

Esto puede reducirse a lo siguiente:

return ((a || b) && (c)) || (a && b);

Pero ahora ya no es divertido.


Cía:

return !!a + !!b + !!c >= 2;


Como una adición a la excelente publicación de @TofuBeer TofuBeer, considere la respuesta de @pdox pdox:

static boolean five(final boolean a, final boolean b, final boolean c) { return a == b ? a : c; }

Considere también su versión desensamblada según lo dado por "javap -c":

static boolean five(boolean, boolean, boolean); Code: 0: iload_0 1: iload_1 2: if_icmpne 9 5: iload_0 6: goto 10 9: iload_2 10: ireturn

La respuesta de pdox se compila en menos código de bytes que cualquiera de las respuestas anteriores. ¿Cómo se compara su tiempo de ejecución con los demás?

one 5242 ms two 6318 ms three (moonshadow) 3806 ms four 7192 ms five (pdox) 3650 ms

Al menos en mi computadora, la respuesta de pdox es solo un poco más rápida que la respuesta de @moonshadow moonshadow, haciendo de pdox el más rápido en general (en mi portátil HP / Intel).


En Ruby:

[a, b, c].count { |x| x } >= 2

Que podría ejecutarse en JRuby en el JavaVM. ;-)


La forma más sencilla (IMO) que no es confusa y fácil de leer:

// Three booleans, check if two or more are true return ( a && ( b || c ) ) || ( b && c );


Probablemente no esté buscando nada complicado como los operadores de comparación bit a bit (normalmente no complicado, pero con booleanos, es extremadamente extraño usar operadores bitwise) o algo que es muy rotundo como convertir a int y resumirlos.

La forma más directa y natural de resolver esto es con una expresión como esta:

a ? (b || c): (b && c)

Póngalo en una función si lo prefiere, pero no es muy complicado. La solución es lógicamente concisa y eficiente.


Una interpretación literal funcionará en todos los idiomas principales:

return (a ? 1:0) + (b ? 1:0) + (c ? 1:0) >= 2;

Pero probablemente facilitaría la lectura de la gente y la expandiría a más de tres, algo que muchos programadores parecen olvidar:

boolean testBooleans(Array bools) { int minTrue = ceil(bools.length * .5); int trueCount = 0; for(int i = 0; i < bools.length; i++) { if(bools[i]) { trueCount++; } } return trueCount >= minTrue; }


Function ReturnTrueIfTwoIsTrue(bool val1, val2, val3)) { return (System.Convert.ToInt16(val1) + System.Convert.ToInt16(val2) + System.Convert.ToInt16(val3)) > 1; }

Demasiadas maneras de hacer esto ...


boolean atLeastTwo(boolean a, boolean b, boolean c) { return ((a && b) || (b && c) || (a && c)); }


return (a==b) ? a : c;

Explicación:

Si a==b , entonces ambos son verdaderos o ambos son falsos. Si ambos son verdaderos, hemos encontrado nuestros dos verdaderos booleanos, y podemos devolverlos verdaderos (devolviendo a ). Si ambos son falsos, no puede haber dos booleanos verdaderos incluso si c es verdadero, por lo que devolvemos falso (devolviendo a ). Esa es la (a==b) ? a (a==b) ? a parte ¿Qué pasa con : c ? Bueno, si a==b es falso, entonces exactamente uno de a o b debe ser verdadero, por lo que hemos encontrado el primer booleano verdadero, y lo único que importa es si c también es verdadero, por lo que devolvemos c como la respuesta .


return 1 << $a << $b << $c >= 1 << 2;