Autor Tema: Como trabajar con números de 6 digitos decimales en CCS y con el 18F26J50  (Leído 2549 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Francisco Silva

  • PIC10
  • *
  • Mensajes: 2
Muy Buen Día

Necesito hacer calculos con números de 6 digitos decimales utilizando el compilador CCS y el PIC 18F26J50 pero no me funciona. Compruebo que solo hasta los 5 digitos decimales es preciso y te da cualquier número. Si alguien me podría ayudar se lo agradeceré muchísimo. Muchas Gracias

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Como trabajar con números de 6 digitos decimales en CCS y con el 18F26J50
« Respuesta #1 en: 03 de Junio de 2015, 13:54:17 »
Eso debe ser por que esta limitado. Por lo que lei CCS utiliza:

23 bit mantissa and an 8 bit exponent which in decimal means 6 or 7 significant digits (6.5)

Ahora entra la parte del por que del problema. Tenes que acordarte que el PIC usa binario. Como hay numeros que pueden representarse directamente, como hay numero que no.

Por ejemplo

1/2 = 0.5 = 0.1
1/4 = 0.25 = 0.01
y
1/3  = .010101101101101101101101101101101101101101 y continua.

Ese numero es imposible de representarlo, lo cual si lo truncas a 23bits  terminas perdiendo informacion
Entonces puede que tu numero sea un numero irrepresenntable con esa cantidad de bits y por eso no da una solucion exacta.

Segun wikipedia:

El IEEE 754:

Single precision, usually used to represent the "float" type in the C language family (though this is not guaranteed). This is a binary format that occupies 32 bits (4 bytes) and its significand has a precision of 24 bits (about 7 decimal digits).

Double precision, usually used to represent the "double" type in the C language family (though this is not guaranteed). This is a binary format that occupies 64 bits (8 bytes) and its significand has a precision of 53 bits (about 16 decimal digits).

Asi que si queres representar algo de esa forma o vas a tener que realizar vos tu propio codigo para una doble presicion o vas a tener que buscar alguno. Obviamente esto no es nada "barato" computacionalmente y en espacio de ROM y RAM
Por otra parte... podrias intentar realizar la operacion en 2 partes, pero esto te dejaria con 2 numeros float, y que tal ves no sirvan a tu proposito, o tal ves puedas pasarl oa string y tratar de juntarlos. Tampoco se la precision que tendrias.

Sino recurrir a un DSP con puto flotante para esa cantidad de digitos. Pero imagino que es muchisimo mas preferible perder 1 numero decimal y no la cantidad de dinero que necesitas para ese DSP
Tambien la opcion de tener un micro con DSP con coma flotante de simple precision y ayudarse con eso para llegar a la doble precision. Esto es mas cercano, pero requiere un gran cambio de todo, herramientas,programadores,etc,etc,etc ( el Cortex M4F tiene esto)
« Última modificación: 03 de Junio de 2015, 14:05:31 por KILLERJC »

Desconectado Francisco Silva

  • PIC10
  • *
  • Mensajes: 2
Re: Como trabajar con números de 6 digitos decimales en CCS y con el 18F26J50
« Respuesta #2 en: 03 de Junio de 2015, 15:24:36 »
La verdad que no estoy trabajando con números infinitos, sino con coordenadas geograficas como -25.456812 y lo unico que tengo que calcular es la distancia cada cierto tiempo entre dos coordenadas pero el resultado no es muy eficiente ya que solo me es preciso hasta el quinto digito decimal. Podría ser porqué no es pago el CCS que utilizo?. Gracias

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Como trabajar con números de 6 digitos decimales en CCS y con el 18F26J50
« Respuesta #3 en: 03 de Junio de 2015, 16:38:35 »
Creo que no me estas entendiendo lo que quise decir.

VOS como cualquier persona maneja el sistema decimal, por lo tanto el numero -25.456812 puede ser reprensentado de forma finita en esta base

EL MICRO se maneja con binario a pesar que tus variables vos pienses que son decimales. Y no puede representar todos los numeros decimales por ser finito. Como el ejemplo que di, de 1/4 y 1/3, pensaste que como 1/3 =0.33333 infinito la representacion binaria era infinita tambien. Pero tal ves te quede mas claro con este ejemplo:

1/10 = 0.1 decimal = .0001100110011001100110011001100110011001100110011001100110011001100110011001100110011001100110011 infinito binario

Si observas un numero finito y facil de representar en decimal, en binario es infinito.
Ese es tu problema, y segundo que CCS usa manejo de flotantes de precisión simple, sea pago o pirateado.


Veamos claramente con el ejemplo que diste:

Numero: -25.456812 decimal

Representacion Binaria en single precision: 0xC1CBA78D = 11000001 11001011 10100111 10001101

Pero ese binario equivale a : -2.54568119049072265625E1 o -25.4568119049072265625

Ya ahi tenes un error lo cual el ultimo digito se ve cambiado y por lo tanto va a generar ese error que ves, si multiplicas y dividis vas a estar multiplicando por ese numero y no por -25.456812.

Ahora si tuvieras un procesador capaz de realizar las cuentas con doble precision ese numero es :

Binario doble precision: 0xC03974F1A1986B9C =   11000000 00111001 01110100 11110001 10100001 10011000 01101011 10011100
Equivalente al decimal:  -2.54568119999999993297024047934E1 = -25.4568119999999993297024047934

Observaras que es MUCHO mas proximo a tu dato pero aun asi es imposible de representar en binario de forma finita.

Las soluciones creo son las que te di si es que seguis insistiendo hacerlas en el PIC. O implementas un algoritmo de doble precision, o le buscas la forma de hacerlo en 2 partes a lo que necesitas hacer y luego lo juntaras. O simplemente te buscas un micro que maneje flotantes de doble precision.
« Última modificación: 03 de Junio de 2015, 16:49:11 por KILLERJC »