Hola, tengo un problema con la siguiente operación -10/3 + 5*(2/3) .
Debería dar 0 ya que -3.333333 + 3.333333 = 0 pero me da un número con exponente -16.
¿Cuál puede ser el problema?
| |||
Problema con números reales Hola, tengo un problema con la siguiente operación -10/3 + 5*(2/3) . Debería dar 0 ya que -3.333333 + 3.333333 = 0 pero me da un número con exponente -16. ¿Cuál puede ser el problema? |
| ||||
Respuesta: Problema con números reales y por que no le das........ (-10/3) + (5*(2/3) )
__________________ Atte. MasterOjitos :ojotes: Todo sobre Programación Web Las ultimas tendencias en Efectos y Recursos Web: MasterOjitos Blog |
| |||
Respuesta: Problema con números reales Bueno realmente el problema no si es ese, quizá me he explicado mal. Es un programa que resuelve el algoritmo Simplex que no se si conoceréis pero tengo que hacer operaciones sobre filas en una matriz como si se tratara de un sistema de ecuaciones. Entonces un caso me falla porque tengo una fila con -3.3333333 que es el resultado de dividir 10 entre 3 entonces al combinarlo con otra que es 5*(2/3) no da el resultado que debiera. Muchas gracias por responder |
| ||||
Respuesta: Problema con números reales Hola Basmang_15, el tema no es simple, pero por lo que estas haciendo seguramente lo comprendes y verás que es fácil. Hasta donde sabrás los números se guardan en formato binario. Y aquí está el problema. El 1 se almacena exactamente como es, pero algunos otros números en clave decimal como 0.1 no se pueden grabar de manera exacta en binario. Lo mismo te esta pasando con 1/3 que en decimal se convierte en 0.33333..., el número 1/10 (10 en notación decimal, no 10 binario) se convierte en periodico al ser expresado en binario: 0.1 (decimal) = .0001100011000111000111... (binario). Y acá está el tema, éste número se redondea por 2.79E-17 (o algo así) porque la pc lo recortará al número de bits máximos que va a usar. Así que la manera es reducir los periodicos, algo así:
Código:
Claro que esto puede romper el exacto (puedes usar DecimalFormat), pero para tu caso me parece que lo solucionará.uno = numberFormat( (-10 / 3 ),4); dos = numberFormat( 5 * ( 2 / 3 ),4) ; Saludos, y espero no haberte mareado.
__________________ Mi punto de partida es Que Bueno Lo Nuevo |
| |||
Respuesta: Problema con números reales El problema es que los tipos primitivos de datos, float y double, son de precisión finita, por cuestiones de rendimiento, por lo que se producen perdidas significativas de precisión al operar con ellos. La solución es usar los tipos de datos BigDecimal y BigInteger, que tienen precisión indefinida y no tienen estos problemas, a cambio, obviamente, de un menor rendimiento. S!
__________________ Para obtener respuestas, pregunta de forma inteligente o si no, pregunta lo que quieras que yo contestaré lo que me dé la gana. |
| |||
Respuesta: Problema con números reales Cierto el error era ese y gracias por las respuestas. Por ejemplo en números que debe dar 5, claramente da algo así como 5.0000001 y luego hay problemas. Pero lo que pasa que lo que me gustaría es tener un número x de decimales pero que se redondeara por ejemplo si tengo 4.9999999999 que se redondee a cinco pero si tengo 0.666666666667 que se redondee que se yo a 0.6667 o algo así porque entonces al restarlo menos 0.3333 no me daría 0. Pero tampoco quiero utilizar un BigDecimal porque quedaría mal el programa y mas con lo "pijos" que son en mi universidad para corregir. Entonces ¿como puedo operar con un doble y redondear el resultado a 4 o 5 decimales?, además he leido que al redondear por ejemplo 0.0000 es distinto que 0.0 y en esto me fallarían las sentencias if en alguna ocasión. No sabía que java tuviera este problema... No se si me explico |
| |||
Respuesta: Problema con números reales Cita: ¿Quedar mal? Si que el resultado sea correcto sin perder precisión es quedar mal, mal vamos . Y no es que le pase a Java, le pasa a cualquier lenguaje que use una implementación de puntos flotantes con precisión finita por defecto, como por ejemplo le ocurre a C si no usas las librerias matemáticas especiales.Pero tampoco quiero utilizar un BigDecimal porque quedaría mal el programa y mas con lo "pijos" que son en mi universidad para corregir. No queda muy claro exactamente como lo quieres redondear, pero para que lo haga un programa tendrás que expresarlo en lenguaje "formal y determinista". De todas formas para un resultado preciso, hay que usar una precisión indefinida. Lo demás son aproximaciones. S!
__________________ Para obtener respuestas, pregunta de forma inteligente o si no, pregunta lo que quieras que yo contestaré lo que me dé la gana. |
| |||
Respuesta: Problema con números reales No se si consigo explicarme, yo tengo que hacer por decirlo de alguna manera como operaciones de un sistema de ecuaciones sobre filas. Entonces en alguna ocasion como ya comente tengo que dividir 10/3 y dan decimales periódicos entonces lo que no se es como redondearlo de alguna manera que no pierda precisión ya que luego al restarlo cuando lo he hecho con redondeo no me da 0 como debería ser. |
| |||
Respuesta: Problema con números reales A ver, precisión vas a perder seguro, por que calculando numeros de coma flotante en una computadora acabas perdiendo precisión. Lo que ocurre es que con BigDecimal y BigInteger puedes controlar hasta donde controlas la precisión y con las primitivas no. De todas formas, tambien tienes que tener en cuenta el orden de las operaciones. Por ejemplo, * y / son transitivos pero... Cita: Por que la division introduce perdida de precisión y si multiplicas despues, multiplicas esa perdida de precisión y la haces más grande.float resultado = (-10f / 3f) + (5f * 2f / 3f); -> da 0 float resultado = (-10f / 3f) + (5f * (2f / 3f)); -> da 2.3841858E-7 Con BigDecimal, lo mismo: Cita: pero si usas MathContext mc = new MathContext(6); // Precision para los calculos BigDecimal first = new BigDecimal(-10).divide(new BigDecimal(3), mc); BigDecimal second = new BigDecimal(5).multiply(new BigDecimal(2).divide(new BigDecimal(3), mc)); first = first.add(second); -> first es 0.000005 Cita: entonces first te devolvera 0.000000BigDecimal second = new BigDecimal(5).multiply(new BigDecimal(2)).divide(new BigDecimal(3), mc); Con BigDecimal puedes decir que quieres precision hasta x digitos y luego redondeas si hace falta. Con las primitivas no sabes que precision tienes, asi que a la hora de redondear, pues no estas seguro cuanto has podido perder. S!
__________________ Para obtener respuestas, pregunta de forma inteligente o si no, pregunta lo que quieras que yo contestaré lo que me dé la gana. |