Ir al contenido



Foto

Pequeña pero notable diferencia (tipo Boolean)


  • Por favor identifícate para responder
12 respuestas en este tema

#1 cram

cram

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 824 mensajes
  • LocationMisiones, Argentina

Escrito 18 septiembre 2014 - 02:54

Conalgunas modificaciones del original y sin importar mucho lo que haga en realidad el procedimiento, se puede ver la gran diferencia de usar un tipo booleano como una variable común y usando sus características de un modo.
En este caso acMod (una acción ) al ejecutarse alterna el foco entre dos objetos y el estado habilitado del objeto dbgLista.
Las diferencias entre una forma de escribir el código y otra son notorias.



delphi
  1. procedure TfrmForm1.acModExecute(Sender: TObject);
  2. // Modo 1.
  3. begin
  4.   if dbgLista.Enabled
  5.   then
  6.     begin
  7.       dbgLista.Enabled:= False;
  8.       edCodObjeto.SetFocus;
  9.     end
  10.   else
  11.     begin
  12.       dbgLista.Enabled:= True;
  13.       dbgLista.SetFocus;
  14.     end;
  15. end;





delphi
  1. procedure TfrmForm1.acModExecute(Sender: TObject);
  2. // Modo2.
  3. begin
  4.   panLista.Enabled:= not panLista.Enabled;
  5.   if panLista.Enabled then dbgLista.SetFocus else edCodObjeto.SetFocus;
  6. end;



Saludos.

  • 0

#2 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.262 mensajes
  • LocationArgentina

Escrito 18 septiembre 2014 - 03:26

Si no es mucha molestia edité tu mensaje para darle la etiqueta delphi.  ;)

Eso me recuerda a mis comienzos en programación cuando hacía cosas como:



delphi
  1. if Encontrado = TRUE
  2.   then ...



Lo que es redundante, y puede hacerse de manera óptima:


delphi
  1. if Encontrado
  2.   then ...



Ahora bien, seguro que el optimizador de código que posee el compilador detecta estas "pifias" y genera un código equivalente a las formas optimizadas como la de nuestros ejemplos.

Saludos,
  • 0

#3 cram

cram

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 824 mensajes
  • LocationMisiones, Argentina

Escrito 18 septiembre 2014 - 04:12

Perdón, ¿pero no es con el signo cardinal? o ¿a eso tengo que cambiar por code = Delphi o algo parecido?
O bueno, quizá me olvidé.

En cuanto al ejemplo me refería mas bien a la inversión de B = not B, que utilizo casi siempre que pueda.
Fijate que es notable la reducción del código de casi diez líneas a solo dos.
Ahora, eso de preguntar B = True, jamás lo hice.

Así por ejemplo, si tengo que preguntar por un número si es impar o par en una secuencia, como un for 1 a 10 en la cual los saltos son de 1 a 10 y es evidente que se alternan de para a impar, prefiero usar una variable booleana e invertirla en cada paso a preguntar si es para o impar, creo que genera un código alguito más eficiente (solo un poquito, pero en suma algo hacen).

Saludos

  • 0

#4 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4.940 mensajes
  • LocationMéxico

Escrito 18 septiembre 2014 - 04:28

Yo al inicio hacía esas validaciones extensas. :p Ahora ya progamo como la sgunda versión que compartió cram.

:p
  • 0

#5 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.262 mensajes
  • LocationArgentina

Escrito 18 septiembre 2014 - 04:43

Perdón, ¿pero no es con el signo cardinal? o ¿a eso tengo que cambiar por code = Delphi o algo parecido?
O bueno, quizá me olvidé.

El botón del signo cardinal pone la etiqueta genérica, CODE. Puedes añadir el texto =delphi para "convertirlo" a Delphi. Hay 2 maneras de usar las etiquetas:

[nobbc]

delphi
  1.  




delphi
  1.  

[/nobbc]

En cuanto al ejemplo me refería mas bien a la inversión de B = not B, que utilizo casi siempre que pueda.
Fijate que es notable la reducción del código de casi diez líneas a solo dos.
Ahora, eso de preguntar B = True, jamás lo hice.

Lo de alternar el valor del boolean al comienzo lo hacía con ifs... luego entendi la forma directa.

Saludos,
  • 0

#6 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.855 mensajes
  • LocationMadrid - España

Escrito 19 septiembre 2014 - 06:32

...si tengo que preguntar por un número si es impar o par en una secuencia, como un for 1 a 10 en la cual los saltos son de 1 a 10 y es evidente que se alternan de para a impar, prefiero usar una variable booleana e invertirla en cada paso a preguntar si es para o impar...


Pues yo para preguntar si un número es par, hago esto:


delphi
  1. Result:= not boolean(n and 1);



Saludos.
  • 0

#7 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 13.993 mensajes
  • LocationMéxico

Escrito 19 septiembre 2014 - 07:41

[ot][/ot]

Perdón, ¿pero no es con el signo cardinal? o ¿a eso tengo que cambiar por code = Delphi o algo parecido?
O bueno, quizá me olvidé.


Antes teníamos etiquetas específicas para cada lenguaje, después de la última actualización no las hemos agregado, estamos en ello, "sorry".

Saludos
  • 0

#8 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.262 mensajes
  • LocationArgentina

Escrito 19 septiembre 2014 - 08:07

...si tengo que preguntar por un número si es impar o par en una secuencia, como un for 1 a 10 en la cual los saltos son de 1 a 10 y es evidente que se alternan de para a impar, prefiero usar una variable booleana e invertirla en cada paso a preguntar si es para o impar...


Pues yo para preguntar si un número es par, hago esto:


delphi
  1. Result:= not boolean(n and 1);



Saludos.

Hay ciertas operaciones en las que resulta más sencillo y rápido hacer un poco de pensamiento lateral como éste. Yo me he preguntado muchas veces para que existe el dezplazamiento de bits a la izquierda y derecha pero con el tiempo me he estado dando cuenta de que con un poco de creatividad es posible recrear una división o multiplicación aprovechando las propiedades y particularidades del sistema binario.
Por ejemplo, y si no me falla la cabeza, creo que esto es lo mismo:



delphi
  1. res1 := variable DIV 32;
  2. res2 := variable shr 5;



Cuando se tiene muchas operaciones que hacer y hay que ganar lo más posible en velocidad, no queda otra que hacer ese esfuerzo extra en reducir lo más posible las cosas. Ejemplos como el que describes amigo para determinar si es par o impar lo he visto en tutoriales de gaming. Proponía esa forma de determinar la paridad debido a que al parecer los lenguajes de programación toman al módulo de forma diferentes cuando se trata de números negativos. Hay algunos en los que si el resultado es -1 y otros en los que es siempre +1.
Yo me quedé en cero cuando leí eso. ¿Será cierto?

Saludos,
  • 0

#9 genriquez

genriquez

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 520 mensajes
  • LocationCali, Colombia

Escrito 19 septiembre 2014 - 09:59

continuando con las optimizaciones de código, cuando debo verificar si un valor es par o impar utilizo la función Odd




delphi
  1. If Odd(valor) then



solo comentarios. ;)
  • 0

#10 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.855 mensajes
  • LocationMadrid - España

Escrito 19 septiembre 2014 - 11:30

Hay ciertas operaciones en las que resulta más sencillo y rápido hacer un poco de pensamiento lateral como éste. Yo me he preguntado muchas veces para que existe el dezplazamiento de bits a la izquierda y derecha pero con el tiempo me he estado dando cuenta de que con un poco de creatividad es posible recrear una división o multiplicación aprovechando las propiedades y particularidades del sistema binario.

Tienes toda la razón, en concreto para todas aquellas multiplicaciones/divisiones de enteros por/entre potencias de 2.

Yo también uso las operaciones binarias (or, and, xor y not) en aquellos casos en que los grupos valores a comparar/operar de una vez son binarios/booleanos, agrupándolos en un BYTE, WORD o DWORD... Se ahorra código y velocidad.

...Proponía esa forma de determinar la paridad debido a que al parecer los lenguajes de programación toman al módulo de forma diferentes cuando se trata de números negativos. Hay algunos en los que si el resultado es -1 y otros en los que es siempre +1.
Yo me quedé en cero cuando leí eso. ¿Será cierto?


Pues yo no lo se, pero en ese caso no me parece correcto. En todo caso es más rápida una operación binaria and que encontrar el resto de una división.


Saludos.
  • 0

#11 cram

cram

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 824 mensajes
  • LocationMisiones, Argentina

Escrito 19 septiembre 2014 - 11:51

El asunto de donde está situado el bit más significativo es según la codificación (little endian o big endian), pero hay que tener en cuenta que también cambia todo en el programa ejecutable. La verdad, es que como siempre programé para Window, nunca presté mucha atención a eso.
Qué buen truco ese de la división entera, el único inconveniente es que el divisor debe ser potencia de 2, igual es bueno conocer el truco.  (y)
Es un tema importante el hecho que Pascal (Object Pascal, Delhi) puedan hacer manipulaciones sobre los bits, en cierto tiempo las usé ampliamente con grandes beneficios (y no todos los lenguajes poseen dicha capacidad).
Supongo que la función Odd(N) ejecuta un código similar al que propone Escafandra, pero solo es suposición mía.

El asunto de reducir líneas de código a veces puede venir con el inconveniente de un código objeto más ineficiente (no es éste el caso), pero puede darse. Lo importante es que es mucho más fácil para leerlo y pasarlo de largo al buscar código, etc.
El asunto es que Pascal con sus begin y end queda distante de otros lenguajes cuando se habla de caracteres útiles en su código fuente.

A veces es tal mi deseo de acortar el código que preguntaba por funciones que devolvían valores booleanos y me encontré una vez con una característica de optimización, de Pascal que hace que en el caso de un AND, al darse el primer valor negativo ya pasa al ELSE o un OR y hallar verdadero al primer valor pasa al THEN (cuando uno quiere que se ejecuten ambas funciones, hay un problema), pero luego aprendí que existe una directiva de compilación para forzar la respuesta de ambas funciones o mejor dicho evaluar ambas expresiones. No la recuerdo (Strict boolean evaluation, creo).



delphi
  1. writeln('OK');



  • 0

#12 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.262 mensajes
  • LocationArgentina

Escrito 19 septiembre 2014 - 02:28

Tienes toda la razón, en concreto para todas aquellas multiplicaciones/divisiones de enteros por/entre potencias de 2.

Yo también uso las operaciones binarias (or, and, xor y not) en aquellos casos en que los grupos valores a comparar/operar de una vez son binarios/booleanos, agrupándolos en un BYTE, WORD o DWORD... Se ahorra código y velocidad.

Yo en realidad las usé alguna que otra vez. Pero recién ya de grandote y barbudo es que le acepté sus ventajas.  :D


Pues yo no lo se, pero en ese caso no me parece correcto. En todo caso es más rápida una operación binaria and que encontrar el resto de una división.

Saludos.


Te cito las palabras que leí en una guía de programación:

Note that I use a&1 (bitwise and) instead of a%2 (modulo) to detect whether something is even (0) or odd (1). When a is positive, they will produce the same result. However, when a is negative, programming languages differ on what they’ll return. In some languages, -1 % 2 == -1 and in other languages -1 % 2 == +1. In some languages it depends on which compiler and machine you use (!). If your hex coordinates are always non-negative, or if in your language/compiler/machine -1 % 2 == +1, then it makes no difference, and you can use a%2 instead of a&1.


Vaya a saber que lenguajes efectivamente arrojan un negativo. Es tanto el tiempo que he pasado lejos de la programación que ya ni recuerdo que pasa con el caso de Delphi.  :

Saludos,
  • 0

#13 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.262 mensajes
  • LocationArgentina

Escrito 19 septiembre 2014 - 02:35

A veces es tal mi deseo de acortar el código que preguntaba por funciones que devolvían valores booleanos y me encontré una vez con una característica de optimización, de Pascal que hace que en el caso de un AND, al darse el primer valor negativo ya pasa al ELSE o un OR y hallar verdadero al primer valor pasa al THEN (cuando uno quiere que se ejecuten ambas funciones, hay un problema), pero luego aprendí que existe una directiva de compilación para forzar la respuesta de ambas funciones o mejor dicho evaluar ambas expresiones. No la recuerdo (Strict boolean evaluation, creo).

A lo que te refieres, yo lo recuerdo bajo el nombre complete boolean evaluations. Creo recordar vagamente de que todos los lenguajes por defecto hacen una evaluación incompleta, excepto Visual Basic.
Esto lo hacen por cuestiones de optimización. En un AND basta con determinar si el 1er miembro es FALSE para descartar una siguiente evaluación. Y en un OR con que el 1er miembro sea un TRUE es suficiente para dar por positivo el resultado.
Lo que no recuerdo bien es la directiva, y en que casos es que efectivamente se requiere de una evaluación completa.

Saludos,
  • 0