Warum ist der Float-Datentyp auf einem STM32 nicht genau?

Ich verwende STM32F103C8T6 und mein Compiler ist KEIL 5. Ich habe ein einfaches Programm geschrieben, um etwas zu überprüfen, aber ich habe einen interessanten Punkt herausgefunden. Wenn ich das Programm auf die MCU herunterlade aaaund muss und bbbsein , aber wenn ich das Programm auf der MCU debugge, werden die Anfangswerte dieser Variablen zu diesen: und . das Programm:12.5662.8aaa=12.5600004bbb=62.8000031

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

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

Denken Sie auch daran, wenn ich floatzu ändere double, funktioniert es ohne Probleme.

Floating Point ist immer nur eine Annäherung. Genauso wie man nicht alle Ziffern von 1/3 dezimal schreiben kann. docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html für ausführlichere Informationen.
Es ist nicht auf den STM32 beschränkt, Sie werden dieses Verhalten auf jedem Computer sehen, auf dem Sie diesen Code ausprobieren.
Siehe auch fast jeden Artikel auf Prof. Kahans Seite ... cs.berkeley.edu/~wkahan ... einschließlich www.cs.berkeley.edu/~wkahan/JAVAhurt.pdf

Antworten (3)

Fließkommazahlen werden als Summe binärer Brüche mal einer Zweierpotenz dargestellt. Bei IEEE-754-Gleitkommazahlen mit einfacher Genauigkeit reichen die Brüche von 1 / 2 0 Zu 1 / 2 23 und die Zweierpotenzen reichen von 2 126 Zu 2 127 . Zum Beispiel:

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 16 ) 2 3 = 1,5625 8 = 12.5
62 = ( 1 1 + 1 2 + 1 4 + 1 8 + 1 16 ) 2 5 = 1,9375 32 = 62

Aber 0,06 und 0,8 lassen sich auf diese Weise eben nicht gleichmäßig darstellen 1 / 3 kann nicht als Summe von Dezimalbrüchen dargestellt werden:

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

Die Dezimaldarstellungen können von System zu System variieren. Ich werde nicht viel Zeit damit verbringen, weitere Beispiele zu schreiben, denn hoffentlich haben Sie die Idee inzwischen verstanden. Wichtig ist, dass Gleitkommazahlen binäre rationale Zahlen sind , auch wenn Sie dezimale rationale Zahlen in Ihren Quellcode einfügen!

Fließkommazahlen sollen Näherungswerte darstellen. Wenn Sie exakte Werte darstellen müssen, verwenden Sie ganze Zahlen oder eine andere Alternative . Wenn Sie nicht wissen, ob Sie Fließkommazahlen benötigen, tun Sie dies wahrscheinlich nicht.

Für weitere Informationen habe ich festgestellt, dass der Floating Point Guide leichter zu lesen ist als Goldbergs Essay , aber beide sind wertvoll.

Die Kommentare haben die Grundlagen behandelt, aber für ein vollständiges Verständnis dessen, was vor sich geht, empfehle ich You're Going To Have To Think! das ist eine Reihe von Artikeln.

Kurz gesagt, Floats/Doubles sind Annäherungen, da sie eine unendliche Menge von Werten in eine Darstellung mit fester Größe quetschen müssen, sodass es immer zu Annäherungsfehlern kommt. Um nicht überrascht zu werden, wie und wann diese Fehler auftreten, müssen Sie vollständig verstehen, wie Floats funktionieren.

Die Artikel beschreiben nicht nur die Prinzipien gut, sondern beginnen auch mit einem großartigen Intro:

Der Drache des numerischen Fehlers wird nicht oft aus seinem Schlummer geweckt, aber wenn er sich unvorsichtig nähert, fügt er den Berechnungen des unvorsichtigen Programmierers gelegentlich katastrophalen Schaden zu.

So sehr, dass einige Programmierer, die ihn zufällig in den Wäldern der IEEE 754-Gleitkommaarithmetik getroffen haben, ihren Kollegen davon abraten, in dieses schöne Land zu reisen.

In dieser Artikelserie werden wir die Welt des numerischen Rechnens erkunden und die Fließkommaarithmetik einigen der Techniken gegenüberstellen, die als sicherer Ersatz dafür vorgeschlagen wurden. Wir werden erfahren, dass das Territorium des Drachen tatsächlich weitreichend ist und dass wir im Allgemeinen vorsichtig vorgehen müssen, wenn wir seine verheerende Aufmerksamkeit fürchten.

Es gibt einen App-Hinweis von STMicroelectronics, „ AN4044 Application Note Using Floating-Point Unit (FPU) with STM32F405/07xx and STM32F415/417xx microcontrollers “. Ich glaube nicht, dass Ihr STM32F103C8T6 eine Hardware-Gleitkommaeinheit (FPU) hat, aber es ist immer noch interessant zu lesen.

Alle ARM-Prozessoren sowie praktisch jeder andere aktuelle Mikroprozessor/Mikrocontroller verwenden einen Standard namens IEEE 754-1985, um Gleitkommazahlen darzustellen. Es wurde 1985 eingeführt und seine erste Verwendung in einer Hardware-FPU war der 8087-Chip von Intel, der ein Begleiter des 8086 war. (Der ursprüngliche Standard wurde tatsächlich durch einen neueren namens IEEE-2008 ersetzt, der abwärtskompatibel ist. )

Die beiden Hauptformate des IEEE-Standards sind 32 Bit (in C Float genannt) und 64 Bit (in C Double genannt):

Geben Sie hier die Bildbeschreibung ein

(Diese Abbildung wurde aus dem App-Hinweis übernommen, auf den ich zuvor verwiesen habe.)

Vor 1985 war die Darstellung von Gleitkommazahlen von Hersteller zu Hersteller unterschiedlich, zum Beispiel hatten die in den 1960er Jahren eingeführten IBM 360-Mainframes ein ähnliches Format, aber der Exponent in der Gleitkommadarstellung mit einfacher Genauigkeit war 7 Bit anstelle von 8, und der vorzeichenlose ganzzahlige Teil war 24 Bit statt 23. Er hätte also ein Bit mehr Auflösung gehabt, aber nur einen Exponentenbereich von -62, +63 statt -126, +127. Das Digital Equipment VAX-11-Format war wirklich bizarr .

Andere haben eine Menge Mathematik eingebaut, um die Ungenauigkeit verschiedener Gleitkommazahlen zu zeigen, aber nur auf einer intuitiven Basis, wenn Sie nur den 23-Bit-Integer-Teil eines Gleitkommas plus das 1-Bit-Vorzeichen und ein entsprechendes 24-Bit-Vorzeichen betrachten ganze Zahl, die einen maximalen Wert von ±10 hat 23 , oder ±8388608, und richten Sie diesen Wert mit einem Ihrer Gleitkommazahlen mit einfacher Genauigkeit aus,

    8388608
 12.5600004

Sie werden sehen, dass die Genauigkeit ungefähr gleich ist. Ich bin mir sicher, dass alle Mathematikexperten an diesem Punkt stöhnen, ich versuche nur zu zeigen, wie man das aus einer Höhe von 50.000 Fuß betrachtet. Jedenfalls hat es mir geholfen, es zu visualisieren.