Cambia valores decimales del double al sumar 1

Consulta, tengo un campo Mysql con valores double decimales ya almacenados.
Lo leo de la base de datos como double, hasta ahí todo bien, pero cuando le sumo 1 me cambia agregando más decimales, porque sucede eso y cómo lo evito.

Ejemplo

Resultado 1 + VALOR
1,0369999999999999
1,0562 (no cambia -OK)
1,0754999999999999
1,1160000000000001
1,1405000000000001
1,1388 (no cambia -OK)
1,1703999999999999

That’s how floating point works. It’s not decimal. Internally It’s base 2 value with a base 2 exponent that represents the NEAREST value we intend to use in decimal. So a 1,037 really ends with something like 1,036999999…

Así es como funciona el punto flotante. No es decimal. Internamente es un valor de base 2 con un exponente de base 2 que representa el valor MÁS CERCANO que pretendemos usar en decimal. Entonces, un 1.037 realmente termina con algo así como 1.036999999…

Hay alguna función que me ayude a obtener los decimales queridos?
He encontrado otras entradas en el foro pero no logre solucionarlo y tampoco pude con el Round.

¿Dónde quieres almacenar el valor? Si es un Double, ya tienes el valor posible.

Si es en un DOUBLE, ya que en un string puedo hacer que me lo devuelva bien, pero si lo paso al double vuelve a quedar mal.
Pero el DOUBLE no obtengo el valor exacto que necesito.

Pues tu problema esta desde el diseño de la base de datos. Si necesitas valores exactos, deberias de usar columnas almacenadas como DECIMAL no como DOUBLE.

Ya en xojo, puedes usar Currency en vez de Double

Pero solo puede conservar 4 decimales asi.

No es la idea en los MySQL puedo tener decimales tanto como defina, pero luego quiero redondear a determinados, cosa que con el VB6 hacia muy simple.
Puedo entender que rutinas como toDouble reaccionen de determinada forma, pero porque no existe algo que las redondee como lo necesitamos?.

Multiplíca datos y operadores por una constante predefinida (p.e. 100000) y al final, al guardarlos, divide por la misma constante.

Correcto es lo que comentaba antes, ahora 4 me sirven, pero un día puedo querer más.
El problema no debe estar en la cantidad, sino en porque no me las proporciona luego de obtenerlas todas (double).
Lo que me extraña es funciones como Round u otra (que quizás no conozca) no solucionen éste tema.
También veo en foros que son charlas de hace varios años y me parece raro que no se hayan incorporado.

Lo probe con el ROUND como dice en los ejemplos, pero no me funcionó.
Busque rutinas en el foro como: RoundDblToNplaces que postearon y tampoco.

Termina con el mismo valor fraccionario original cuando se normaliza

 r = Round((d * 100)+0.01) / 100

o

  r =ceil((d * 100)) / 100

Independientemente de lo que intente cuando use un Double, siempre puede terminar con una pequeña fracción, como un 1.23456794563 (hipotéticamente) redondeado a 2 dígitos que terminariam como algo como 1.23000000000000387

No se que me sucede pero me devuelve lo mismo:
En el campo tengo VALOR = 0.037

Código:
dblINTERES = larsRecordset.Column(“VALOR”).DoubleValue + 1
// el problema esta al + 1 si muestro el VALOR sin +1 es correcto

Según lo pasado:

dblINTERES = Round((dblINTERES*10000)+0.5) / 10000

ó

dblINTERES = Ceil((dblINTERES*10000)) / 10000

Me devuelve:

1,0370999999999999

Correcto!

No hace lo que necesito

La solución más cercana, para no contentarme con que el double me da un valor erróneo (lo necesito para un calculo financiero), es pasar esa variable a Currency como comentan que ya contempla 4 decimales, PERO uno de mis valores tiene 5 decimales, como dije antes, no es lo que estaba buscando pero parece que es lo que tengo que usar por ahora.

Reitero, puedo entender que el double se comporte asi en momentos pero debería haber algo que le indique que lo “resuelva” de la forma que seria la “normal” para la mayoría. Es mi humilde opinión.

Lo primero que debes entender es que NO TE DA UN VALOR ERRONEO, te da el valor que puede representar.

Lo segundo, como lo menciona CUALQUIER lenguaje de programación, no se debe usar un DOUBLE para calculos financieros debido a los problemas de exactitud INTRINSECOS de un Double.

Una vez entendiendo que estas viendo el comportamiento correcto que se espera de un Double, puedes buscar algún metodo alternativo para obtener los resultados que quieres usando un tipo de dato que no esta diseñado para eso.

guardar el valor en un tipo d campo diferente a double no ayuda en nada si lo q ud hace es pasarlo a double.

yo utilizo double, es +preciso, el problema es en ciertas operaciones donde hacemos partida doble (equidad contable), como ejemplo los descuentos pie factura en una compra, c debe prorratear ese descuento a todos los items de la factura, una operación línea a línea NUNCA dará exacto al descuento pie factura, la solución mía es calcular el descuento total y restar cada línea así el último elemento le asigno el resto del descuento píe factura, ahora bien, si guardo esos valores en double, al efectuar nuevamente esa operación dará, otra vez, valores aproximados. en esos casos sigo utilizando el tipo double, pero multiplicado por el número d decimales q quiera y redondeado, obvio el nombre del campo es algo como: “desctox10000r”

lo q quiero decir es q el tipo d campo q c guarde es intrascendente a las operaciones, en la mayoría d las operaciones financieras funcionará double, en ciertas operaciones c debe ser exacto con el número d decimales y prevenir discrepancias haciendo operaciones inversas al efectuar nuevamente el cálculo.

Forum for Xojo Programming Language and IDE. Copyright © 2021 Xojo, Inc.