Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Varios
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 09-03-2011
Avatar de marcoszorrilla
marcoszorrilla marcoszorrilla is offline
Capo
 
Registrado: may 2003
Ubicación: Cantabria - España
Posts: 11.221
Poder: 10
marcoszorrilla Va por buen camino
Obtener un número positivo o negativo.

En una tabla guardo abonos y cargos los abonos tienen que ser negativos y los cargos positivos. El objeto es que al facturar cargue o abone dichas cantidades.

El propósito es, independientemente de la buena voluntad del usuario que los bultos y unidades sean positivas o negativas dependiendo de lo explicado anteriormente.

Código Delphi [-]
//Empece así:
procedure TDmAbon.IBDtsAbonBeforePost(DataSet: TDataSet);
begin
 if Es_Abono = True then
 begin
 DmAbon.IBDtsAbonBULTOS.AsFloat  :=Sqr(Power(DmAbon.IBDtsAbonBULTOS.Value,2))*-1;
 DmAbon.IBDtsAbonUNIDADES.AsFloat:=Sqr(Power(DmAbon.IBDtsAbonUNIDADES.Value,2))*-1;
 end
 else
 begin
 DmAbon.IBDtsAbonBULTOS.AsFloat  :=Sqr(Power(DmAbon.IBDtsAbonBULTOS.Value,2));
 DmAbon.IBDtsAbonUNIDADES.AsFloat:=Sqr(Power(DmAbon.IBDtsAbonUNIDADES.Value,2));
 end;

end;


//Lo remedé así:

procedure TDmAbon.IBDtsAbonBeforePost(DataSet: TDataSet);
begin
 if Es_Abono = True then
 begin
 DmAbon.IBDtsAbonBULTOS.AsInteger  :=ABS(DmAbon.IBDtsAbonBULTOS.Value)*-1;
 DmAbon.IBDtsAbonUNIDADES.AsInteger:=ABS(DmAbon.IBDtsAbonUNIDADES.Value)*-1;
 end
 else
 begin
 DmAbon.IBDtsAbonBULTOS.AsInteger  :=ABS(DmAbon.IBDtsAbonBULTOS.Value);
 DmAbon.IBDtsAbonUNIDADES.AsInteger:=ABS(DmAbon.IBDtsAbonUNIDADES.Value);
 end;

end;

Alguna otra idea?

Un Saludo.
__________________
Guía de Estilo de los Foros
Cita:
- Ça c'est la caisse. Le mouton que tu veux est dedans.

Última edición por marcoszorrilla fecha: 09-03-2011 a las 13:28:42.
Responder Con Cita
  #2  
Antiguo 09-03-2011
Avatar de Ñuño Martínez
Ñuño Martínez Ñuño Martínez is offline
Moderador
 
Registrado: jul 2006
Ubicación: Ciudad Catedral, Españistán
Posts: 6.000
Poder: 25
Ñuño Martínez Tiene un aura espectacularÑuño Martínez Tiene un aura espectacular
La solución de calcular el valor absoluto y luego multiplicar o no por -1 me parece la más cómoda. No sé si sería más eficiente comprobar los valores:
Código Delphi [-]
  IF ValorPositivo < 0 THEN
    ValorPositivo := ValorPositivo * (-1);
  IF ValorNegativo > 0 THEN
    ValorNegativo := ValorNegativo * (-1);
Vamos, que no sé cómo está implementado "ABS", porque si el compilador la expande como hace, por ejemplo, con INC y DEC entonces creo que da lo mismo, casi.
__________________
Proyectos actuales --> Allegro 5 Pascal ¡y Delphi!|MinGRo Game Engine
Responder Con Cita
  #3  
Antiguo 09-03-2011
Avatar de marcoszorrilla
marcoszorrilla marcoszorrilla is offline
Capo
 
Registrado: may 2003
Ubicación: Cantabria - España
Posts: 11.221
Poder: 10
marcoszorrilla Va por buen camino
Gracias Ñuño, creo que lo dejaré tal como está. Que conste que antes de hacer cosas como está pronuncio internamente "la polvora la inventaron los chinos...".

Un Saludo.
__________________
Guía de Estilo de los Foros
Cita:
- Ça c'est la caisse. Le mouton que tu veux est dedans.
Responder Con Cita
  #4  
Antiguo 09-03-2011
Avatar de Delphius
[Delphius] Delphius is offline
Miembro Premium
 
Registrado: jul 2004
Ubicación: Salta, Argentina
Posts: 5.582
Poder: 25
Delphius Va camino a la fama
Hola,
Creo que lo más adecuado es irse por el valor absoluto. Supuestamente ya está optimizada esta función y debería hacer uso de la instrucción ABS y/o FABS en assembler que justamente lo único que hacen es alterar el campo de signo.

La ventaja del uso del valor absoluto es que no interesa si se ingresa positivo o negativo... siempre se obtiene el "lado positivo" y lo que nos resta por hacer es multiplicarlo por -1 en caso de ser necesario (que es más que evidente que solo aplica para cuando se requiere de los negativos) y no se necesita de hacer evaluaciones previas, como la que sugiere Nuño. Añadir un IF equivale a añadir un V(G) = 2. Dos IFs, son V(G) = 4. A mi humilde ver, me parece algo exagerado contar con una V(G) de 4 sólo para generar positivos y/o negativos.

Cuanto mucho me podría preguntar si da lo mismo hacer:

Código Delphi [-]
Negativo := - Abs(Valor);

Que:

Código Delphi [-]
Negativo := Abs(Valor) * -1;

Saludos,
__________________
Delphius
[Guia de estilo][Buscar]
Responder Con Cita
  #5  
Antiguo 09-03-2011
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
También podrías evitar el condicional:

Código Delphi [-]
DmAbon.IBDtsAbonBULTOS.AsInteger   := (2*Integer(EsAbono) - 1)*ABS(DmAbon.IBDtsAbonBULTOS.Value);
DmAbon.IBDtsAbonUNIDADES.AsInteger := (2*Integer(EsAbono) - 1)*ABS(DmAbon.IBDtsAbonUNIDADES.Value);

// Saludos
Responder Con Cita
  #6  
Antiguo 09-03-2011
[coso] coso is offline
Miembro Premium
 
Registrado: may 2008
Ubicación: Girona
Posts: 1.678
Poder: 0
coso Va por buen camino
Hola,
tambien podrias asignar directamente el bit de paridad con un or (no recuerdo cual es) aunque supongo que es lo que debe hacer abs o algo bastante parecido.
Saludos.
Responder Con Cita
  #7  
Antiguo 09-03-2011
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Poder: 29
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
Yo también optaría por una solución como la de Román, dándole simetría aritmética al condicionante Boolean. Pero a esa variable le daría un significado positivo, es decir, la llamaría EsCargo (que de hecho es el sentido que adquiere el código de Román).

Saludos.
Responder Con Cita
  #8  
Antiguo 09-03-2011
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Cita:
Empezado por Al González Ver Mensaje
que de hecho es el sentido que adquiere el código de Román
Je, je. Me equivoqué. Sería así:

Código Delphi [-]
DmAbon.IBDtsAbonBULTOS.AsInteger   := (-2*Integer(EsAbono) + 1)*ABS(DmAbon.IBDtsAbonBULTOS.Value);
DmAbon.IBDtsAbonUNIDADES.AsInteger := (-2*Integer(EsAbono) + 1)*ABS(DmAbon.IBDtsAbonUNIDADES.Value);

Por otro lado, también podría optarse por crear disparadores before insert y before update para asegurar las signaturas correctas en la base.

// Saludos
Responder Con Cita
  #9  
Antiguo 09-03-2011
Avatar de marcoszorrilla
marcoszorrilla marcoszorrilla is offline
Capo
 
Registrado: may 2003
Ubicación: Cantabria - España
Posts: 11.221
Poder: 10
marcoszorrilla Va por buen camino
Me gusta la solución de Román, gracias también al resto que me habeis dado pautas interesantes.

Decir que Es_Cargo es una variable de tipo Boolean que le paso desde el menú y que se analiza en el evento de apertura del formulario para saber cual de las dos opciones se está ejecutando.


Por otra parte como veis el código va en el evento:
Código Delphi [-]
procedure TDmAbon.IBDtsAbonBeforePost(DataSet: TDataSet);
begin
Para que cada vez que se ejecute algún cambio en los datos se actualice el valor.

Un Saludo.
__________________
Guía de Estilo de los Foros
Cita:
- Ça c'est la caisse. Le mouton que tu veux est dedans.
Responder Con Cita
  #10  
Antiguo 09-03-2011
Avatar de Ñuño Martínez
Ñuño Martínez Ñuño Martínez is offline
Moderador
 
Registrado: jul 2006
Ubicación: Ciudad Catedral, Españistán
Posts: 6.000
Poder: 25
Ñuño Martínez Tiene un aura espectacularÑuño Martínez Tiene un aura espectacular
Cita:
Empezado por coso Ver Mensaje
Hola,
tambien podrias asignar directamente el bit de paridad con un or (no recuerdo cual es) aunque supongo que es lo que debe hacer abs o algo bastante parecido.
Saludos.
No exactamente. En las computadoras binarias modernas, para obtener el negativo de un entero hay calcular el su complemento binario, de esta forma:
Código Delphi [-]
FUNCTION Complemento (Valor: INTEGER): INTEGER;
BEGIN
  RESULT := (NOT Valor) + 1;
END;

Por ejemplo, para el -3:
Código:
Complemento ( 3) = NOT ( 3) + 1 = NOT (0011) + 0001 = 1100 + 0001 = 1101 = -3
Complemento (-3) = NOT (-3) + 1 = NOT (1101) + 0001 = 0010 + 0001 = 0011 =  3
Esto mantiene la coherencia matemática:
Código:
 4 - 7 = 4 + (-7) = -3

0100 - 0111 = 0100 + 1001 = 1101
Incluso con el cero:
Código:
NOT (0) + 1 = NOT (0000) + 0001 = 1111 + 0001 = 0000
__________________
Proyectos actuales --> Allegro 5 Pascal ¡y Delphi!|MinGRo Game Engine
Responder Con Cita
  #11  
Antiguo 09-03-2011
Avatar de Delphius
[Delphius] Delphius is offline
Miembro Premium
 
Registrado: jul 2004
Ubicación: Salta, Argentina
Posts: 5.582
Poder: 25
Delphius Va camino a la fama
Hola,
A ver Nuño, la verdad es que me matas con tu explicación. Entiendo lo que dices, y pareciera ser bastante coherente. Pero que yo sepa hay un estándar en como se guardan los números. Este estándar establece un formato adecuado, y casualmente se destina un campo para indicar si el número es positivo o negativo, parecido al formato que se ha definido para los números flotantes. La diferencia respecto a éste es que no posee campos para exponentes sino un campo para el número en si:

Código:
+-+--- ... ---+
| |           |
+-+--- ... ---+
EDITO:
El estándar indica que los números negativos están expresados en complemento-2. Y resulta ser estos complementos SIEMPRE tienen un 1 en el campo destinado al signo. Las rutinas INVIERTEN este campo, y naturalmente deberá complementar el resto.

En donde si me corrijo es en haber dicho que ABS y FABS únicamente alterar el campo de signo. Pero vamos, que realizar el complemento-2 del número es una rutina más que normal para la máquina por lo que no deberíamos preocuparnos demasiado en bajarnos a estos niveles.

No nos deberíamos complicar demasiado... ya Abs() nos hace fácil la cosa.

Saludos,
__________________
Delphius
[Guia de estilo][Buscar]

Última edición por Delphius fecha: 09-03-2011 a las 21:06:22.
Responder Con Cita
  #12  
Antiguo 09-03-2011
[coso] coso is offline
Miembro Premium
 
Registrado: may 2008
Ubicación: Girona
Posts: 1.678
Poder: 0
coso Va por buen camino
Cierto, confundi el bit de paridad con el de signo, y no se bien bien si existe. Gracias por la aclaracion, Ñuño.
Responder Con Cita
  #13  
Antiguo 11-03-2011
Avatar de Ñuño Martínez
Ñuño Martínez Ñuño Martínez is offline
Moderador
 
Registrado: jul 2006
Ubicación: Ciudad Catedral, Españistán
Posts: 6.000
Poder: 25
Ñuño Martínez Tiene un aura espectacularÑuño Martínez Tiene un aura espectacular
Cita:
Empezado por Delphius Ver Mensaje
(...) Pero que yo sepa hay un estándar en como se guardan los números. (...)
Pues eso: el complemente binario o "complemento a dos" es la norma más usada en la representación de números binarios con signo. Para punto flotante se usa otro método cuya base matemática es algo más obscura.
__________________
Proyectos actuales --> Allegro 5 Pascal ¡y Delphi!|MinGRo Game Engine
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Saber Número negativo y pasarlo a positivo BuRtOn Varios 3 19-09-2008 20:36:15
Obtener numero de línea de código Walterdf Varios 5 13-06-2008 11:28:29
De un número, obtener el ASCII Alexander Varios 2 26-05-2005 17:21:32
obtener el numero de linea. maruenda Varios 1 30-10-2004 05:11:05
Obtener el número de conexiones a una BD repo Firebird e Interbase 2 31-05-2004 18:46:00


La franja horaria es GMT +2. Ahora son las 22:25:28.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi