¿Por qué el tipo de datos flotantes no es preciso en un STM32?

Estoy usando STM32F103C8T6 y mi compilador es KEIL 5. Escribí un programa simple para verificar algo pero descubrí un punto interesante. Cuando descargo el programa a la MCU, aaay bbbtengo que ser 12.56y 62.8, pero cuando depuro el programa en la MCU, los valores iniciales de estas variables se convierten en estos: aaa=12.5600004y bbb=62.8000031. el programa:

#include "stm32f10x.h"
float aaa=12.56,bbb;

int main(void)
{
    bbb=aaa*5;
    while(1){}
}

También ten en cuenta que si cambio floata double, funciona sin problema.

El punto flotante siempre es solo una aproximación. Al igual que no puedes escribir todos los dígitos de 1/3 de forma decimal. docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html para obtener información más detallada.
No está restringido al STM32, verá este comportamiento en cualquier máquina en la que pruebe este código.
Consulte también casi todos los artículos en la página del profesor Kahan... cs.berkeley.edu/~wkahan ... incluido www.cs.berkeley.edu/~wkahan/JAVAhurt.pdf

Respuestas (3)

Los números de coma flotante se representan como una suma de fracciones binarias por una potencia de dos. En números de punto flotante IEEE-754 de precisión simple, las fracciones van desde 1 / 2 0 a 1 / 2 23 y las potencias de dos van desde 2 126 a 2 127 . Por ejemplo:

12 = ( 1 1 + 1 2 ) 2 3 = 1.5 8 = 12
0.5 = ( 1 1 ) 2 1 = 1 1 2 = 0.5
12.5 = ( 1 1 + 1 2 + 1 dieciséis ) 2 3 = 1.5625 8 = 12.5
62 = ( 1 1 + 1 2 + 1 4 + 1 8 + 1 dieciséis ) 2 5 = 1.9375 32 = 62

Pero 0.06 y 0.8 no se pueden representar de manera uniforme de esta manera, al igual que 1 / 3 no se puede representar como una suma de fracciones decimales:

1 3 ( 3 10 + 3 100 + 3 1000 + 3 10000 + ) 0.33333

0.06 ( 1 1 + 1 2 + 1 4 + 1 8 + 1 32 + 1 128 + 1 256 + 1 512 + 1 16384 + 1 65536 + 1 1048576 + 1 2097152 + 1 4194304 + 1 8388608 ) 2 5 1.91999995708465576171875 1 32 0.0599999986588954925537109375

Las representaciones decimales pueden variar de un sistema a otro. No voy a perder mucho tiempo escribiendo más ejemplos, porque espero que ahora entiendas la idea. Lo importante es que los números de coma flotante son números racionales binarios , ¡aunque pongas números racionales decimales en tu código fuente!

Los números de coma flotante pretenden ser aproximados. Si necesita representar valores exactos, use números enteros u otra alternativa . Si no sabe si necesita un punto flotante, probablemente no lo sepa.

Para obtener más información, encontré que la Guía de punto flotante es más fácil de leer que el ensayo de Goldberg , pero ambos son valiosos.

Los comentarios han cubierto los conceptos básicos, pero para una comprensión completa de lo que está pasando, recomiendo ¡ Vas a tener que pensar! que es una serie de artículos.

En resumen, los flotantes/dobles son aproximaciones porque tienen que comprimir una cantidad infinita de valores en una representación de tamaño fijo, por lo que siempre habrá errores de aproximación. Para no sorprenderse de cómo y cuándo aparecen esos errores, debe comprender completamente cómo funcionan los flotadores.

Los artículos no solo hacen un buen trabajo al describir los principios, sino que abren con una gran introducción:

El dragón del error numérico no se despierta a menudo de su sueño, pero si se le acerca con descuido, ocasionalmente infligirá daños catastróficos a los cálculos del programador desprevenido.

Tanto es así que algunos programadores, habiéndolo encontrado por casualidad en los bosques de la aritmética de punto flotante IEEE 754, aconsejan a sus compañeros que no viajen por esa hermosa tierra.

En esta serie de artículos exploraremos el mundo de la computación numérica, contrastando la aritmética de coma flotante con algunas de las técnicas que se han propuesto como reemplazos más seguros para ella. Aprenderemos que el territorio del dragón es de gran alcance y que, en general, debemos andar con cuidado si tememos su devastadora atención.

Hay una nota de aplicación de STMicroelectronics, " Nota de aplicación AN4044 Uso de unidad de punto flotante (FPU) con microcontroladores STM32F405/07xx y STM32F415/417xx ". No creo que su STM32F103C8T6 tenga una unidad de punto flotante (FPU) de hardware, pero sigue siendo una lectura interesante.

Todos los procesadores ARM, así como prácticamente todos los demás microprocesadores/microcontroladores actuales, utilizan un estándar llamado IEEE 754-1985 para representar números de coma flotante. Fue adoptado en 1985 y su primer uso en una FPU de hardware fue el chip 8087 de Intel, que era un complemento del 8086. (El estándar original en realidad fue reemplazado por uno más nuevo llamado IEEE-2008, que es compatible con versiones anteriores. )

Los dos formatos principales en el estándar IEEE son de 32 bits (llamado flotante en el lenguaje C) y de 64 bits (llamado doble en C):

ingrese la descripción de la imagen aquí

(Esta figura está adaptada de la nota de la aplicación a la que me referí anteriormente).

Antes de 1985, la representación de números de punto flotante variaba de un fabricante a otro, por ejemplo, los mainframes IBM 360 presentados en la década de 1960 tenían un formato similar, pero el exponente en la representación de punto flotante de precisión simple era de 7 bits en lugar de 8, y la parte entera sin signo era de 24 bits en lugar de 23. Por lo tanto, tendría un bit más de resolución, pero solo un rango de exponente de -62,+63 en lugar de -126,+127. El formato Digital Equipment VAX-11 fue realmente extraño .

Otros han incluido un montón de matemáticas para mostrar la imprecisión de varios números de punto flotante, pero solo de manera intuitiva, si observa solo la parte entera de 23 bits de un flotante, más el signo de 1 bit y los 24 bits correspondientes con signo entero que tiene un valor máximo de ±10 23 , o ±8388608, y alinee ese valor con uno de sus flotadores de precisión individuales,

    8388608
 12.5600004

Verá que la precisión es más o menos la misma. Estoy seguro de que todos los expertos en matemáticas se quejan en este punto, solo trato de mostrar cómo mirar esto desde un nivel de 50,000 pies. De todos modos me ayudó a visualizarlo.