Foros del Web » Programación para mayores de 30 ;) » C/C++ »

[SOLUCIONADO] Duda sobre representación de números decimales

Estas en el tema de Duda sobre representación de números decimales en el foro de C/C++ en Foros del Web. Hola Foro, luego de una larga temporada los saludo de nuevo. Os traigo una duda existencial jeje, quizá sea algo básico pero no me queda ...
  #1 (permalink)  
Antiguo 20/04/2020, 02:07
 
Fecha de Ingreso: junio-2014
Mensajes: 144
Antigüedad: 5 años, 11 meses
Puntos: 1
Duda sobre representación de números decimales

Hola Foro, luego de una larga temporada los saludo de nuevo.

Os traigo una duda existencial jeje, quizá sea algo básico pero no me queda claro qué pasa.

Tengo un código que hace mogollón de cálculos con decimales, para corroborar que lo hace bien, hice unas pruebas en excel. Luego de varias correcciones, y con la seguridad que lo hacía bien me daba cuenta que excel decía una cosa y mi código otra (muy similar pero diferente); y me dí de esto:



y este era el problema, que aunque por precisión sea muy parecido, luego de muchos cálculos los resultados difieren significativamente. Eso sin contar con que 0.0058999999 no es 0.0059.

Esto tiene solución?, para que coincida con excel por ejemplo.

Muchas gracias por su atención equipo.

Saludos,
  #2 (permalink)  
Antiguo 20/04/2020, 05:14
 
Fecha de Ingreso: abril-2011
Mensajes: 123
Antigüedad: 9 años, 1 mes
Puntos: 43
Respuesta: Duda sobre representación de números decimales

Internamente, es imposible. Los tipos float y double no son capaces de almacenar con total precisión las cifras decimales de un número porque trabajan con fracciones.

Lo que sí puedes hacer es imprimir con printf el valor redondeando a x cifras decimales (%.xf), por ejemplo:

Código C:
Ver original
  1. double jjaa = 0.00589;
  2.  
  3. printf("%.4f", jjaa); // 0.0059
  4.  
  5. printf("%.3f", jjaa); // 0.006

Pero esto no evita que en memoria estén almacenados de forma imprecisa.

  #3 (permalink)  
Antiguo 20/04/2020, 06:51
 
Fecha de Ingreso: junio-2014
Mensajes: 144
Antigüedad: 5 años, 11 meses
Puntos: 1
Respuesta: Duda sobre representación de números decimales

Muchas gracias por tu respuesta. De ser así, cómo hace google para funcionar bien, o las calculadoras o bien excel?

Es una limitante de c++?

Saludos,
  #4 (permalink)  
Antiguo 20/04/2020, 08:48
 
Fecha de Ingreso: abril-2011
Mensajes: 123
Antigüedad: 9 años, 1 mes
Puntos: 43
Respuesta: Duda sobre representación de números decimales

No es algo específico de C/C++. Ocurre en casi todos, por no decir todos los lenguajes.

La única solución a esto es utilizar librerías que realicen las operaciones manualmente.

En el caso de la calculadora de Google, me imagino que estará utilizando alguna librería tipo MathJS, que permite que las operaciones con decimales sean precisas, pero a JavaScript le ocurre lo mismo nativamente. Por ejemplo:

Código Javascript:
Ver original
  1. 0.1 + 0.2

Esto arroja 0.30000000000000004.
  #5 (permalink)  
Antiguo 20/04/2020, 14:53
 
Fecha de Ingreso: junio-2014
Mensajes: 144
Antigüedad: 5 años, 11 meses
Puntos: 1
Respuesta: Duda sobre representación de números decimales

Muchas gracias,

Comprendo, estoy buscando si en c+ hay alguna alternativa. He encontrado 2 una es usar floats que se supone da mejor y la segunda es una librería de boost.

Saludos,
  #6 (permalink)  
Antiguo 21/04/2020, 02:51
 
Fecha de Ingreso: abril-2011
Mensajes: 123
Antigüedad: 9 años, 1 mes
Puntos: 43
Respuesta: Duda sobre representación de números decimales

Me imagino que te refieres a Boost.Multiprecision. No parece nada fácil de usar.

Yo te recomendaría pasarte a Java. Mira qué sencillo es hacerlo con Java:

https://www.javamexico.org/blogs/lux...os_financieros

No es por ser un detractor de C/C++, pero hay que reconocer que el tiempo que ahorras usando Java es bestial.
  #7 (permalink)  
Antiguo 24/04/2020, 13:50
 
Fecha de Ingreso: junio-2014
Mensajes: 144
Antigüedad: 5 años, 11 meses
Puntos: 1
Respuesta: Duda sobre representación de números decimales

Muchas gracias. Lamentablemente tengo todo montado en c++ y pasarme a java sería complicado.

Que lío esto de los decimales y la precisión parece que lo mejor es usar enteros multiplicados por 10^x.

Saludos,
  #8 (permalink)  
Antiguo 24/04/2020, 16:01
 
Fecha de Ingreso: abril-2011
Mensajes: 123
Antigüedad: 9 años, 1 mes
Puntos: 43
Respuesta: Duda sobre representación de números decimales

Buscando en github he encontrado una librería de precisión para decimales y enteros escrita en C++:

https://github.com/Sam-bit/BigDecimal-CPP

La acabo de probar y definitivamente es mejor opción que Boost. Te adjunto un ejemplo:

Código C++:
Ver original
  1. #include "BigDecimal.h"
  2. #include <iostream>
  3. #include <iomanip>
  4.  
  5. using namespace std;
  6.  
  7. int main(int argc, char** argv) {
  8.     // usando la libreria
  9.     BigDecimal C;
  10.     BigDecimal A("0.1");
  11.     BigDecimal B("0.2");
  12.     C = A + B;
  13.     cout << "C = " << C.toString() << endl; // 0.3
  14.  
  15.     // forma nativa (con error)
  16.     float a = 0.1;
  17.     float b = 0.2;
  18.     float c = a + b;
  19.     cout << "C = " << setprecision(10) << c << endl; // 0.3000000119 (tiene un pequeño error de 0.0000000119)
  20. }

PD: Evidentemente, puedes utilizar cualquier operador aritmético (+-/*), no solo suma.

PD2: El método toString() solamente lo debes utilizar cuando quieras imprimir un número en pantalla. Para realizar operaciones, es igual que en C/C++ solo que declarando tipo BigDecimal.


Última edición por prueba230683; 25/04/2020 a las 08:11
  #9 (permalink)  
Antiguo 27/04/2020, 17:23
 
Fecha de Ingreso: junio-2014
Mensajes: 144
Antigüedad: 5 años, 11 meses
Puntos: 1
Respuesta: Duda sobre representación de números decimales

Mil gracias!!!

La probaré ahora mismo.

Un abrazo.
  #10 (permalink)  
Antiguo 28/04/2020, 06:35
 
Fecha de Ingreso: abril-2011
Mensajes: 123
Antigüedad: 9 años, 1 mes
Puntos: 43
Respuesta: Duda sobre representación de números decimales

Otra cosa. Algunas veces (no entiendo por qué) tira por stderr lo siguiente:

Cita:
Scale (-2147483648) Cant Be Negative!!!
Parece ser un pequeño bug, porque doy fe de que funciona bien (al menos, para operaciones aritméticas):

Código C++:
Ver original
  1. #include <iomanip>
  2. #include <iostream>
  3. #include "BigDecimal.h"
  4.  
  5. using namespace std;
  6.  
  7. int main() {
  8.   BigDecimal C;
  9.   BigDecimal A("1");
  10.   BigDecimal B("1000000000000000000000000000000000000000000000000000000000000");
  11.   BigDecimal D("2");
  12.   C = A / B;
  13.   cout << "C = " << C.toString() << endl; // 0.000000000000000000000000000000000000000000000000000000000001
  14.   C = C / D;
  15.   cout << "C = " << C.toString() << endl; // 0.0000000000000000000000000000000000000000000000000000000000005
  16.   C = C + (A / B);
  17.   cout << "C = " << C.toString() << endl; // 0.0000000000000000000000000000000000000000000000000000000000015
  18.   C = C * D;
  19.   cout << "C = " << C.toString() << endl; // 0.000000000000000000000000000000000000000000000000000000000003
  20. }

Yo comentaría todos los std::cerr en BigDecimal.cpp para que no te lance errores innecesarios.

PD: También he visto en el código que tiene soporte para algunos operadores más: potencia ^, módulo % etc.

Última edición por prueba230683; 03/05/2020 a las 10:29



La zona horaria es GMT -6. Ahora son las 14:21.