In order for this site to work correctly we need to store a small file (called a cookie) on your computer. Most every site in the world does this, however since the 25th of May 2011, by law we have to get your permission first. Please abandon the forum if you disagree.
Para que este foro funcione correctamente es necesario guardar un pequeño fichero (llamado cookie) en su ordenador. La mayoría de los sitios de Internet lo hacen, no obstante desde el 25 de Marzo de 2011 y por ley, necesitamos de su permiso con antelación. Abandone este foro si no está conforme.
Para que este foro funcione correctamente es necesario guardar un pequeño fichero (llamado cookie) en su ordenador. La mayoría de los sitios de Internet lo hacen, no obstante desde el 25 de Marzo de 2011 y por ley, necesitamos de su permiso con antelación. Abandone este foro si no está conforme.
Increible locura con Val( )
Increible locura con Val( )
Vamos a ver que le pasa a Harbour con esto
LogDebug(Val("6.55"))
LogDebug(Val("7.55"))
LogDebug(Val("8.55"))
LogDebug(Val("9.55"))
Y el resultado es
#16: 6.55
#17: 7.55
#18: 8.550000000000001
#19: 9.550000000000001
De que chistera saca este conejo????
Salu2.
LogDebug(Val("6.55"))
LogDebug(Val("7.55"))
LogDebug(Val("8.55"))
LogDebug(Val("9.55"))
Y el resultado es
#16: 6.55
#17: 7.55
#18: 8.550000000000001
#19: 9.550000000000001
De que chistera saca este conejo????
Salu2.
BiSoft Desarrollo de software profesional
http://www.bisoft.es
http://www.bisoft.es
Re: Increible locura con Val( )
Bingen,
viene de la chistera de los números en punto flotante
Echa un vistazo a esto: http://puntoflotante.org
viene de la chistera de los números en punto flotante

Echa un vistazo a esto: http://puntoflotante.org
Re: Increible locura con Val( )
Interesante artículo.
Ya tenía claro que en las operaciones se utilizaba la coma flotante, pero si no se hace ninguna operación y si solo quiero mostrar un valor es casi ridículo.
Por ejemplo obtengo unos valores que quiero presentar con un Round(nValor,2)
MsgInfo(Round(10.8974358974359,2))
MsgInfo(Round(8.888888888888889,2))
y el resultado es
10.90 correcto redondeado y presentado con 2 decimales
8.890000000000001 ridículo que le pasa a Round no vale, hay alguna otra alternativa.
Gracias
Ya tenía claro que en las operaciones se utilizaba la coma flotante, pero si no se hace ninguna operación y si solo quiero mostrar un valor es casi ridículo.
Por ejemplo obtengo unos valores que quiero presentar con un Round(nValor,2)
MsgInfo(Round(10.8974358974359,2))
MsgInfo(Round(8.888888888888889,2))
y el resultado es
10.90 correcto redondeado y presentado con 2 decimales
8.890000000000001 ridículo que le pasa a Round no vale, hay alguna otra alternativa.
Gracias
BiSoft Desarrollo de software profesional
http://www.bisoft.es
http://www.bisoft.es
- ignacio
- Site Admin
- Mensajes: 9447
- Registrado: Lun Abr 06, 2015 8:00 pm
- Ubicación: Madrid, Spain
- Contactar:
Re: Increible locura con Val( )
Hola,
Round(x,2) == Round(y,2)
Nunca me ha fallado. No obstante siempre puedes quitar los decimales multiplicando por un múltiplo de 10 y luego usando la función Int() para forzar que no sea tratado como coma flotante
Saludos
Round(x,2) == Round(y,2)
Nunca me ha fallado. No obstante siempre puedes quitar los decimales multiplicando por un múltiplo de 10 y luego usando la función Int() para forzar que no sea tratado como coma flotante
Saludos
Ignacio Ortiz de Zúñiga
[OZ Software]
https://www.ozs.es
--
[Equipo de Xailer / Xailer team]
https://www.xailer.com
[OZ Software]
https://www.ozs.es
--
[Equipo de Xailer / Xailer team]
https://www.xailer.com
Re: Increible locura con Val( )
Gracias Ignacio, lo que nos propones es exactamente lo que estamos haciendo ahora multiplicando por múltiplos de 100, tomar la parte entera y dividir por 100, pero hay unos valores que ni así salen bien.
MsgInfo(Int(8.888888888888889*100)) --> 888
MsgInfo(Int(8.888888888888889*100)/100) --> 8.880000000000001
Parece iconcebible que ni Round() haga bien su trabajo truncando este número.
Hay alguna otra alternativa???
Salu2
MsgInfo(Int(8.888888888888889*100)) --> 888
MsgInfo(Int(8.888888888888889*100)/100) --> 8.880000000000001
Parece iconcebible que ni Round() haga bien su trabajo truncando este número.
Hay alguna otra alternativa???
Salu2
BiSoft Desarrollo de software profesional
http://www.bisoft.es
http://www.bisoft.es
- ignacio
- Site Admin
- Mensajes: 9447
- Registrado: Lun Abr 06, 2015 8:00 pm
- Ubicación: Madrid, Spain
- Contactar:
Re: Increible locura con Val( )
A mi modo de ver si que hay alternativas y creo que ya se han dicho en este hilo. Para cualquier operación excepto comparaciones con <, > , <=, =>, =, !, o <> no nay que hacer absolutamente nada. Si por el contrario se trata de comprarar dos valores, utiliza ROUND() como te he comentado (repito, a mi nunca me ha fallado) y si quieres máxima seguridad conviértelos en enteros múltiplicando por múltiplos de 10, pero obviamente no los vuelvas a dividir por nada. Es decir:bingen escribió:Gracias Ignacio, lo que nos propones es exactamente lo que estamos haciendo ahora multiplicando por múltiplos de 100, tomar la parte entera y dividir por 100, pero hay unos valores que ni así salen bien.
MsgInfo(Int(8.888888888888889*100)) --> 888
MsgInfo(Int(8.888888888888889*100)/100) --> 8.880000000000001
Parece iconcebible que ni Round() haga bien su trabajo truncando este número.
Hay alguna otra alternativa???
Salu2
IF INT( 8.88888888888888 * 100 ) == INT( 8.8889999999999999 * 100 )
Creo que este hilo no da mucho más de si. Lo siento.

Saludos
Ignacio Ortiz de Zúñiga
[OZ Software]
https://www.ozs.es
--
[Equipo de Xailer / Xailer team]
https://www.xailer.com
[OZ Software]
https://www.ozs.es
--
[Equipo de Xailer / Xailer team]
https://www.xailer.com
Re: Increible locura con Val( )
Bingen,
creo que estamos perdiendo el norte con este tema... todo el problema viene de las conversiones decimal->binario y binario->decimal de los números de coma flotante. Hay ciertos números que son perfectamente representables en decimal pero que en binario son periódicos, o no tienen una representración 100% exacta. Y lo mismo pasa al revés. P.ej., 2/3 no se puede representar exactamente en decimal; puede ser 0.67 ó 0.6667 ó 0.6666667, etc.
Cuando un número no se puede representar de forma exacta en binario, entonces es cuando pueden aparecer errores de cálculo, ya que todas las operaciones se realizan en binario (formato IEEE 754) dentro del procesador. Pero otras muchas veces, los cálculos son perfectamente exactos, y lo que no está bien es su representación decimal cuando mostramos el resultado.
El caso que nos ocupa está directamente relacionado con esto último... la función para mostrar el resultado. Tú estás usando LogDebug(), que internamente utiliza ToString() para convertir cualquier valor a cadena, para poder mostrarla en la ventana del debugger del IDE. Pues bien, esta función ToString() ya la hemos tenido que modificar un par de veces por problemas similares. Si pones LogDebug( 8.88 ), el resultado será 8.880000000000001, pero si pones LogDebug( Str( 8.88 ) ) el resultado será exacto. Es más, para que veas que el problema es solamente la conversión, si pones LogDebug( 8.88 + 1.11 ), el resultado es exactamente 9.99
Y sí, sé que me vas a decir que entonces ToString() tiene algún bug y hace mal la conversión. Pues no exactamente. Es que 8.88 convertido a decimal desde su representación interna binaria es 8.880000000000001, y no 8.88. En todo caso, el que está redondeando (para bien o para mal) es Str(). Str() tiene en cuenta muchas cosas, incluido el valor de SET DECIMALS, pero nosotros expresamente decidimos no hacerlo igual porque la finalidad de ToString() no es la misma que Str(). Si quieres mostrar un resultado, usa Str(), y para todo lo demás ToString().
Lo digo porque ya ocurrió una vez, que modificamos ToString() para que funcionara igual que Str() y nos tropezamos con el problema de que se estaban redondeando valores que no debían redondearse. Ahora bien, la confusión surge precísamente de lo que he dicho al principio, que LogDebug() utiliza internamente ToString(), y eso puede llevar a todo este lio. Pero eso no significa que esté mal.
creo que estamos perdiendo el norte con este tema... todo el problema viene de las conversiones decimal->binario y binario->decimal de los números de coma flotante. Hay ciertos números que son perfectamente representables en decimal pero que en binario son periódicos, o no tienen una representración 100% exacta. Y lo mismo pasa al revés. P.ej., 2/3 no se puede representar exactamente en decimal; puede ser 0.67 ó 0.6667 ó 0.6666667, etc.
Cuando un número no se puede representar de forma exacta en binario, entonces es cuando pueden aparecer errores de cálculo, ya que todas las operaciones se realizan en binario (formato IEEE 754) dentro del procesador. Pero otras muchas veces, los cálculos son perfectamente exactos, y lo que no está bien es su representación decimal cuando mostramos el resultado.
El caso que nos ocupa está directamente relacionado con esto último... la función para mostrar el resultado. Tú estás usando LogDebug(), que internamente utiliza ToString() para convertir cualquier valor a cadena, para poder mostrarla en la ventana del debugger del IDE. Pues bien, esta función ToString() ya la hemos tenido que modificar un par de veces por problemas similares. Si pones LogDebug( 8.88 ), el resultado será 8.880000000000001, pero si pones LogDebug( Str( 8.88 ) ) el resultado será exacto. Es más, para que veas que el problema es solamente la conversión, si pones LogDebug( 8.88 + 1.11 ), el resultado es exactamente 9.99
Y sí, sé que me vas a decir que entonces ToString() tiene algún bug y hace mal la conversión. Pues no exactamente. Es que 8.88 convertido a decimal desde su representación interna binaria es 8.880000000000001, y no 8.88. En todo caso, el que está redondeando (para bien o para mal) es Str(). Str() tiene en cuenta muchas cosas, incluido el valor de SET DECIMALS, pero nosotros expresamente decidimos no hacerlo igual porque la finalidad de ToString() no es la misma que Str(). Si quieres mostrar un resultado, usa Str(), y para todo lo demás ToString().
Lo digo porque ya ocurrió una vez, que modificamos ToString() para que funcionara igual que Str() y nos tropezamos con el problema de que se estaban redondeando valores que no debían redondearse. Ahora bien, la confusión surge precísamente de lo que he dicho al principio, que LogDebug() utiliza internamente ToString(), y eso puede llevar a todo este lio. Pero eso no significa que esté mal.
Re: Increible locura con Val( )
Eso es exactamente lo que necesitaba, hacia un ToString y con Str se ha solucionado.
Lo siento Ignacio pero no se trataba de comparar nada, eso si que funciona como tu dices, sino de presentar el valor en pantalla al cliente y el cliente sorprendido no acababa de entender que es el sistema de coma flotante lo que hace que salga así, solo pone cara de tonto y me dice, venga ponlo con 2 decimales y dejate de tonterías.
Salu2 y gracias a los dos.
Lo siento Ignacio pero no se trataba de comparar nada, eso si que funciona como tu dices, sino de presentar el valor en pantalla al cliente y el cliente sorprendido no acababa de entender que es el sistema de coma flotante lo que hace que salga así, solo pone cara de tonto y me dice, venga ponlo con 2 decimales y dejate de tonterías.
Salu2 y gracias a los dos.
BiSoft Desarrollo de software profesional
http://www.bisoft.es
http://www.bisoft.es