Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   ojo con delphi 2006 (https://www.clubdelphi.com/foros/showthread.php?t=34764)

avmm2004 21-08-2006 10:50:17

ojo con delphi 2006
 
Estoy trabajando con delphi 2006 y me he encontrado lo siguiente:

Todas la variables del calculo son Double.

Código Delphi [-]
// primer calculo
    saldo := 0;
    for I := 0 to mes do
      begin
        valor := 0;
        valor := t_debe [i] - t_haber [i];
        saldo := saldo + valor;
      end;
    if dm1.OraQr_mcoMCO_CUENTA.Value = 409000000 then
        showmessage(floattostr(saldo));
 
// segundo calculo
    saldo := 0;
    for I := 0 to mes do
        saldo := saldo + t_debe [i] - t_haber [i];
    if dm1.OraQr_mcoMCO_CUENTA.Value = 409000000 then
        showmessage(floattostr(saldo));

El primer showmessage da 0 ;) y el siguiente da 9,09494701772928E-13 :eek: .

EL valor correcto es 0.

¿ es un tremendo fallo ?
¿ es mi ignorancia ?
¿ es azar ?
¿ es delphi 2006 ?

Estoy seguro que tiene una explicación per se me ha quedado el cuerpo con mal sabor del delphi 2006.
¿¿¿ Alguien conoce la explicacìón ??????? :confused:

Bicho 21-08-2006 11:41:31

Por favor, viendo que eres nuevo en el foro, te recomiendo leer la guia de estilo, intentar dar un título más descriptivo a los hilos para las próximas veces y hacer uso de las etiquetas para el código Delphi, SQL, etc

Saludos y bienvenido al foro.

Ñuño Martínez 21-08-2006 11:48:02

Cita:

Empezado por avmm2004
El primer showmessage da 0 ;) y el siguiente da 9,09494701772928E-13 :eek: .

EL valor correcto es 0.

¿ es un tremendo fallo ?
¿ es mi ignorancia ?
¿ es azar ?
¿ es delphi 2006 ?

Bueno, el error no es tan grande, ya que en lenguaje humano el resultado es 0'000000000000909494791772928, vamos que es casi 0. No he hecho la prueba, pero tal vez el error se deba, precisamente, a que se está usando Double. Este tipo utiliza un sistema de codificación denominado "punto flotante" que permite almacenar un ámplio rango de números (desde tremendamente grandes hasta tremendamente pequeños) y facilita los cálculos pero a costa de perder precisión y exactitud en algunos casos.

Otro sistema de codificación, denominado "punto fijo", podría dar el resultado correcto, pero no permitiría almacenar ciertos números; por ejemplo, le resultaría imposible almacenar el número 0'1.

Un tercer método denominado "binario codificado en decimal" permite mucha más precisión (hasta llegar a la exactitud), pero para almacenar números grandes necesita mucha más memoria que los dos anteriores.

Si esto es cierto, el problema no es del lenguaje ni del compilador sino del microprocesador.

avmm2004 21-08-2006 13:24:51

Problemas con el punto flotante
 
Gracias, por la respuesta tan rápida.
Olvidé mencionar un tema.
Todos los valores que tienen las tablas y que se cargan previamente (no incluí el código para no poner un montón de líneas) son 0 o valores con dos decimales como máximo (positivos y negativos).
Y las cantidades ninguna sobrepasa en la parte entera el valor 99999.
Por cierto la tabla solo tiene 13 elementos, con lo cual con ¿ningun calculo ? me puede dar un valor tan alto.

Lepe 21-08-2006 17:08:32

Si estas trabajando con datos monetarios usa el tipo de dato Currency, tanto en la base de datos como en delphi, así solo cogerá los 2 primeros decimales.

Si usas Firebird como base de datos, debes crear el campo como NUMERIC(10,2) y dialecto 3.

Como ya te han dicho, es un problema inherente al tipo de datos Float. Además tambien influye el Epsilon de la máquina, que es el número más pequeño que puede se puede definir con total precisión en ese ordenador.

Por cierto: Diez Billonésimas parte de 1 euro/peso/peseta/dolar es ¿un valor tan alto? ;)

Saludos

Mick 21-08-2006 17:15:10

Te estas confundiendo, no te esta dando ningun valor alto, simplemente un valor pequeñisimo muy proximo a cero.
Este numero esta en notacion cientifica:
9,09494701772928E-13
Que se correponde a (como ya han explicado en otro post)
0'000000000000909494791772928
Es decir un numero muy pequeño proximo a cero.

Es posible incluso que alguno de los valores que tienes guardados en la base de datos no sean exactamente cero, pero la herramienta o el software con el que los ves lo redondeara a un numero determinado de cifras decimales de modo que te parecera que valen 0 aunque no sea asi.

Esto te pasara en cualquier ordenador y cualquier compilador, al trabajar con numeros en punto flotante.

Saludos

avmm2004 21-08-2006 18:16:44

A lo que yo voy es a lo siguiente:

Si se fijan hay dos formulas de cálculo en el código.
Ambas hacen exactamente lo mismo y los resultados son diferentes.

Eso es lo que mas me preocupa.
Entiendo y agradezco todos los comentarios anteriores pero no entiendo que ambas formulas den un resultado diferente (cuando hacen lo mismo).

Si ambas formulas dieran igual, puedo entender casi todo, pero no puedo entender que segun haga el calculo (bien por supuesto) me de un resultado o otro, con el mismo set de datos.

Por cierto, no utilizo Firebird utilizo Oracle 9i y la definición del campo, por casualidad es numeric (10,2).

Gracias.

egostar 21-08-2006 19:05:04

El tema como dicen atinadamente todos es por el valor de punto flotante, pero porque no haces esto:

Código Delphi [-]
 
// segundo calculo
saldo := 0; for I := 0 to mes do
        saldo := saldo + (t_debe [i] - t_haber [i]); { Propiedad asociativa }
    if dm1.OraQr_mcoMCO_CUENTA.Value = 409000000 then
        showmessage(floattostr(saldo));

Bueno, todo se vale con tal de salir de nuestras dudas.

Saludos

avmm2004 21-08-2006 19:15:25

Ya lo hice y el resultado es identico. Falla. Gracias.
Yo he pensado que si intervendrá para algo el nuevo gestor de memoria y calculos que trae el delphi 2006, de Pierr la riche o algo asi creo que se llama.
En alguna parte leí, que se debe a el la aceleración en la ejecución del ide de delphi 2006 y en los cálculos en los programas ejecutables resultantes.
No se.

samantha jones 22-08-2006 00:38:53

a) declara saldo como currency
b) al jalar los valores de la la base de datos utiliza el AsCurrency en lugar del Value

Saludos

Mick 22-08-2006 00:55:02

Cita:

Empezado por avmm2004
Ya lo hice y el resultado es identico. Falla. Gracias.
Yo he pensado que si intervendrá para algo el nuevo gestor de memoria y calculos que trae el delphi 2006, de Pierr la riche o algo asi creo que se llama.
En alguna parte leí, que se debe a el la aceleración en la ejecución del ide de delphi 2006 y en los cálculos en los programas ejecutables resultantes.
No se.

Los calculos no son identicos, en el primer caso se restan don valores y despues se realiza una suma.

En el segundo caso se sumas dos valores, y despues se hace una resta.

De modo que en el segundo caso algun o algunos de los valores intermedios de la primera suma no son representables de forma exacta en binario de ahi la diferencia de redondeo.

Tienes que entender que no todos los numeros decimales tienen representacion en binario de modo que en esos casos se guardar el valor binario mas aproximado.

Por ejemplo el valor decimal 69,82 no tiene representacion exacta en formato binaro de modo que si despues de asignar ese valor a una variable de tipo float mandas imprimir esa misma variable, veras que el valor es ligeramente diferente !!!

Aqui tienes un tutorial que explica con ejemplos los errores de redondeo en punto flotante, si te fijas es un tutorial de microsoft relativo a Visual Basic, no de delphi, los errores de redondeo son inherentes a la forma que tienen las computadoras de guardar los datos en punto flotante y no tienen que ver con ningun lenguaje en particular:

http://support.microsoft.com/default...b%3Bes%3B42980

PD: Con el avance continuo de la tecnologia de programacion a lenguajes de mas y mas alto nivel, me parece que se esta olvidando enseñar a la gente las bases de funcionamiento de los ordenadores, cualquier aspirante a desarrollar software deberia aprender antes que nada estas bases, no puede ser que a un programador le coja por sorpresa temas tan basicos como este.
Espero que esta reflexion no la tome nadie a mal ;)

Lepe 22-08-2006 08:55:24

Por otra parte, en la Universidad, más concretamente en la asignatura de Física (que nadie echa cuenta), se explica que siempre se despeje la incógnita de la ecuación y despues se realicen todas las operaciones matemáticas de una sola vez, precisamente para que la calculadora use todos los decimales de la operación (bueno... según la resolución de la calculadora).

Por tanto, no es lo mismo, hacer la operación, guardarla en una variable y despues utilizar el valor, que hacer todos los cálculos de una vez.

Por otra parte, deberías ver como está la ley de tu país acerca del redondeo, al menos en españa (no sé si es regla general) sólo se permite un redondeo en el resultado final de una operación, es decir, no se puede redondear el valor de un porcentaje de descuento, de impuestos, etc, sino unicamente el resultado final (lo que el usuario final debe pagar).

El caso de Numeric(10,2) es específico de Firebird, no puedo asegurar que sea igual en Oracle, deberás ver como guarda internamente los números decimales oracle, quizás esto te valga

Cita:

Empezado por Mick
PD: Con el avance continuo de la tecnologia de programacion a lenguajes de mas y mas alto nivel, me parece que se esta olvidando enseñar a la gente las bases de funcionamiento de los ordenadores, cualquier aspirante a desarrollar software deberia aprender antes que nada estas bases, no puede ser que a un programador le coja por sorpresa temas tan basicos como este.
Espero que esta reflexion no la tome nadie a mal ;)

A mí me enseñaron toda la parafernalia de mantisa, exponente y los distintos formatos, ahora mismo solo recuerdo que era un lio padre. El "corolario" que subrayo, no lo dijeron explicitamente, si se supone que yo debía deducirlo... pues creo que el bosque no me dejó ver el árbol ;). Menos mal que tarde o temprano te das cuenta de esos "fallos".

Saludos

kuan-yiu 22-08-2006 09:19:18

Yo recuerdo perfectamente la clase en la que un profesor escribió en el encerado:
Cita:

(A*B)*C <> A*(B*C)
La cara que se nos quedó a todos... Nos lo explicó (todo el lío de la representación de los números en los diferentes formatos) e hicimos un par de programillas simplones para verlo empíricamente... y mete miedo. Ese día también nos enseñó que las calculadoras mienten :D Fue una clase muy instructiva y divertida.

seoane 22-08-2006 15:04:14

Que las calculadoras engañan nos lo demostraban en los simpsons, los grandes maestros de nuestro tiempo :D . En este otro hilo explicaba como David X. Cohen , uno de los creadores de los simpsoms y además con master en Computación por la Universidad de Berkeley, deslizaba en uno de los capítulos una formula que parecía contradecir el teorema de Fermat, precisamente aprovechando los errores de calculo que cometen las calculadoras.

avmm2004 22-08-2006 17:30:24

Cita:

Empezado por Mick
.....

......

Aqui tienes un tutorial que explica con ejemplos los errores de redondeo en punto flotante, si te fijas es un tutorial de microsoft relativo a Visual Basic, no de delphi, los errores de redondeo son inherentes a la forma que tienen las computadoras de guardar los datos en punto flotante y no tienen que ver con ningun lenguaje en particular:

http://support.microsoft.com/default...b%3Bes%3B42980

PD: Con el avance continuo de la tecnologia de programacion a lenguajes de mas y mas alto nivel, me parece que se esta olvidando enseñar a la gente las bases de funcionamiento de los ordenadores, cualquier aspirante a desarrollar software deberia aprender antes que nada estas bases, no puede ser que a un programador le coja por sorpresa temas tan basicos como este.
Espero que esta reflexion no la tome nadie a mal ;)


Muchas gracias. El artículo me ha aclarado algunas cosas. Por cierto la traducción del artículo automática es detestable, he preferido leerlo en inglés. En cuanto al pie (PD), considero que se admiten muchas consideraciones al respecto de lo que es básico y primordial y de lo que es adicional o suplementario. (Claramente es una afirmación gratuita y no era eso lo que yo estaba buscando). Respecto al resto, gracias de nuevo.

roman 22-08-2006 19:51:30

No veo porqué consideras gratuito un comentario que a todas luces se te hizo con buena intención. ¿Dudas que sea un tema básico? Pues sí lo es aun cuando tú no lo conozcas. Esto no tiene nada de malo, pero no es correcto dar la voz de alarma sin más bases que nuestra ignorancia y mucho menos echarla en cara a quien se toma el tiempo y la molestia de ayudarnos.

// Saludarnos

dec 22-08-2006 20:06:05

Hola,

A alguien que no estudió p... punto, pero, aficionado a esto de picar código, este Hilo le resulta interesante y fascinante a la vez. Muchas veces esa "magia" que dicen que existe en los ordenadores, compiladores, y lenguajes de programación, como toda "magia", es producto del conocimiento, por un lado, y del desconocimiento, por otro, ambos encontrados (mejor que enfrentados) por la tozuda realidad. ¿Que no? ;)

avmm2004 22-08-2006 22:49:34

De verdad crees que puedes ayudar a una persona, sea quien sea, diciendole en que se equivoca y luego diciendole que le faltan conocimientos de base ..... y demas. El, te ha pedido su ayuda, si quieres darsela, no un repaso de que es lo que sabe o no, ni de lo que debería saber (ese es su problema). Por eso, es un comentario gratutito que nadie te ha pedido. Nadie, ademas se dedica a dar alarmas, porque esto es un foro de gente con dudas y desconocimientos para ayudarnos y los titulos o mensajes no salen de la prepotencia del conocimiento sino de la certeza del desconocimiento.

Creo que el tema queda zanjado con esto ¿no?

Gracias.

Mick 22-08-2006 22:56:18

Siento que al final se haya tomado a mal mi comentario, quizas podria haber sido un poco menos brusco en la expresion de mis ideas, precisamente por eso puse la ultima frase en la postdata porque me parecio que mi ultima afirmacion habia quedado un poco brusca, pero como realmente en ese momento no estaba por la labor de rehacer el post y expresarlo de otra forma, pense que con esa ultima frase seria suficiente.

Realmente en los foros siempre procuro dar explicaciones o informacion tecnica sobre los temas, y no me suelo parar a pensar si algo que digo puede molestar a alguien o no. Cuando en cualquier post digo que algo esta mal o es erroneo sobre alguna informacion de otra persona, no pretendo ofender a esa persona, tomarlo siempre en cuenta como una afirmacion meramente tecnica, que si, que quizas podria decir "eso no parece del todo correcto" u otras frases menos bruscas pero, siendo los foros eminentemente tecnicos, normalmente no me paro a pulir lo que escribo, y espero que la gente entienda el fondo de la cuestion no la forma.

Lo cierto es que comente este tema, primero porque lo pienso asi y segundo motivado por la insistencia en afirmar que el programa "seguia fallando", ha pesar de que previamente ya se habian dado varias explicaciones del tema.

Esa afirmacion tambien fue la que me hizo buscar alguna informacion de una fuente "mas prestigiosa" por asi decirlo, para ver si asi podiamos convencer
a "avmm2004" de que su programa no tenia nada de malo.

En cuanto a pensar si este tema es mas o menos basico, yo los sigo creyendo asi: La razon es simple, lo unico que hace cualquier programa es operar con numeros sumar , restar , multiplicar y dividir, de modo que si esto es lo unico que sabe hacer un programa cae de cajon que es imprescindible entender como suma, resta, multiplica y divide un computador, precisamente para poder asegurar que nuestros programas y nuestros calculos funcionan como es debido.

Y con este post no se si habre arreglado algo o todo lo contrario !!!!. Por si acaso no lo pienso releer ;).

Saludos

roman 22-08-2006 22:58:00

Sí. Sí considero que cuando alguien de forma educada me señala mis equivocaciones es de gran ayuda para así no volver a cometerlas. Más aún, si me indican que se trata de algo básico; lejos de ofenderme, me indica que es un área en la que debo poner especial atención.

Y sí. Si estás dando una voz de alarma, cuando titulas tu hilo con

ojo con delphi 2006

creando la impresión de que algún problema grave existe en esa aplicación, antes de averiguar si de verdad es un problema.

Y sí. Sí considero zanjado el asunto.

// Saludos


La franja horaria es GMT +2. Ahora son las 16:52:34.

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