Wie behebt man Rundungsfehler auf dem Mikrocontroller?

Hier sind die Spezifikationen für den Chip/die Chipfamilie , die unser Anbieter verwendet.

Für unser Produkt bitten wir sie, eine Berechnung durchzuführen, indem sie eine Zahl mit einem Faktor multiplizieren, der einen Dezimalpunkt hat ... zum Beispiel: 1,07, 0,93 usw.

Wir bitten sie dann, auf die nächste ganze Zahl zu runden.

Die Zahl, die sie berechnen, weist jedoch manchmal einen Rundungsfehler auf. Beispiel: Auf meinem Taschenrechner 56 * 2,36 = 132,16 ... gerundet auf 132. Der Mikrocontroller gibt jedoch eine Antwort von 133 zurück, die auf einem LCD unseres Produkts angezeigt wird.

Meine Frage ist, wie kann man das beheben? Ich habe den Verkäufer viele Male gefragt, und sie können es anscheinend nicht richtig machen.

Ist die Berechnung der Gleitkommazahl für Mikrocontroller, die diese native Funktion nicht haben, wirklich schwierig? (Verwandte Frage: DIY FP – Implementieren von Gleitkomma-Mathematik auf einem Mikrocontroller ohne Hardware-FPU )

UPDATE Der Bereich für die Ergebnisse liegt zwischen 1 und 780.

Besteht die Möglichkeit, dass sie die falsche Rundungsfunktion verwenden und statt der nächsten Ganzzahl nach oben runden?
Dies könnte leicht ein Fehler im Anwendungscode sein und nicht in der Implementierung von Fest-/Gleitkomma-Mathematik.

Antworten (4)

Sie sagen nichts über den Umfang Ihrer Zahlen oder die erforderliche Genauigkeit aus. Aber Sie brauchen dafür oft kein Fließkomma, Festkomma reicht oft aus. Arbeiten Sie einfach mit ganzen Zahlen und setzen Sie an einer bestimmten Stelle einen virtuellen Dezimalpunkt. Eine 16-Bit-Zahl könnte beispielsweise 8 Bits links vom Dezimalkomma und 8 Bits danach haben. Dadurch erhalten Sie einen Bereich von 0 bis 255 (ich gehe von vorzeichenlosen Zahlen aus) mit einer Genauigkeit von besser als 0,01.

Das Runden ist dann einfach: Schauen Sie sich einfach die höchstwertige Dezimalstelle an, das Bit direkt rechts vom Dezimalkomma. Wenn das eine Null ist, sollte der ganzzahlige Teil unberührt bleiben. Wenn es eine Eins ist, fügen Sie 1 zum ganzzahligen Teil hinzu.

Bearbeiten
Es gibt unzählige Rundungsarten: auf-/abrunden, auf den nächsten Wert runden, auf Null runden, Bankrundung, ... Stellen Sie sicher, dass Sie und der Verkäufer die gleiche Sprache sprechen.

Ich denke, es ist nur eine Frage der Präzision.

Angenommen, der Faktor 2,36 wird durch eine Festkommazahl mit nur 4 Bits rechts vom Dezimalkomma (Bruchbits) dargestellt, erhalten Sie:

56 * 2.36 in fixed point representation with only 4 fractional bits:
(56 * round(2.36 * 2^4)) / 2^4 = 
(56 * round(37.76)) / 16 =
(56 * 38) / 16 = 133

Die Lösung wäre, einfach mehr Bruchbits (vielleicht 8) zu verwenden.

56 * 2.36 in fixed point representation with 8 fractional bits:
(56 * round(2.36 * 2^8)) / 2^8 = 
(56 * round(604.16)) / 2^8 =
(56 * 604) / 256 = 132

Aber dennoch ist es möglich, dass einige Faktoren den gleichen Effekt erzielen, nur weniger wahrscheinlich/häufig.

Es funktioniert nur dann immer einwandfrei, wenn die Festkommadarstellung des Faktors keine Bits durch Rundung verliert.

Dies ist der Fall, wenn (und nur wenn):

  • der Bruchteil des Faktors ist ein Vielfaches von 1/2^n und
  • die Festkommadarstellung des Faktors verwendet mindestens n Bruchbits.

Zuerst müssen Sie die Rundung zwischen Ihnen und dem Anbieter definieren, sie haben es möglicherweise basierend auf ihrer Definition richtig gemacht.

Zweitens, wenn Sie nur über zwei Dezimalstellen sprechen, gibt es keinen Grund, Fließkomma zu verwenden, Sie sollten es ohne Fließkomma angegeben haben, und vielleicht können Sie es ändern, um es so zu definieren, dass es kein Fließkomma verwendet. 8-Bit-Mikro oder nicht, nicht erforderlich, kann problemlos 8- oder 16-Bit-Mathematik ausführen und alle gewünschten Rundungen für ein paar Dezimalstellen aussortieren (ein kompetenter Programmierer benötigt niemals Gleitkomma-Hardware, da er immer in der Lage sein sollte, den Punkt in seinem zu behalten Kopf, John von Neumann zugeschrieben).

Egal ob Mikrocontroller oder Cray, Fließkommaformate haben Probleme, Compiler ebenso wie Programmierer. So wie 1/3 und 2/3 ein Problem in einer dezimalen Welt sind, ist beispielsweise 1/10 ein Problem in binärbasierten Gleitkommaprogrammen. Wenn ich 2/3 zu 0,83 addieren möchte, ist 0,667 + 0,83 = 1,49 ... oder 0,67 + 0,83 = 1,50, das eine würde aufrunden, das andere nicht, beide könnten als richtig argumentiert werden. Ja, richtig, Sie müssen immer noch Ihre Rundung definieren, wenn Sie Festkomma verwenden (nehmen Sie 200/3 und erhalten 66 (entspricht 0,66) oder verwenden Sie Rundung und nehmen ((400/3) + 1)/2) und erhalten 67 ?) Ihre Frage teilt nicht, sondern multipliziert, Sie haben immer noch die gleichen Probleme. Beachten Sie auch, dass Gleitkommazahlen in der Hardware in einem Prozessor nicht besonders aufregend sind. Es ist viel schwieriger, die Fehler zu umgehen, die wahrscheinlich dort sind (der Pentium war weder die erste noch die letzte FPU mit Problemen, Ihr Betriebssystem muss sie beheben, oder vielleicht lassen sie sie einfach dort, damit Sie heutzutage scheitern). Eine Soft-FPU ist langsamer, aber viel einfacher zu reparieren, nachdem der Chip in Produktion ist.

2,36 ist wie 1/3 ist zu dezimal, es ist eine sich wiederholende Ziffer, wenn es in binärem Fließkomma dargestellt wird. dieses Bitmuster erscheint ziemlich früh. 101110000101000111 (doppelt leichter zu sehen als einfach, einmal doppelt gesehen, kann man es dann auch im Einzel sehen). Ich kann das oder eine abgekürzte Version davon jedoch nicht dazu bringen, genug Fehler zu verursachen, um es auf 133 zu verschieben. Betrachten Sie IEEE mit einfacher Genauigkeit, das nicht das einzige Gleitkommaformat ist ...

01000000000101110000101000111101 2.36
01000000000101110110110110110111 (132.5/56 = ~2.36607...)

die 110 wiederholt sich und wird am Backend gerundet. nicht, dass dies an dieser Stelle im entferntesten damit zusammenhängt, sondern nur eine Kuriosität, ändern Sie es

01000000000101110110110110110110

mal 56 und du bekommst 132.499...

Die Quintessenz ist, dass Sie, wie Sie hier gesagt haben, wenn Sie Bleistift und Papier verwenden oder einen Taschenrechner verwenden und 56 * 2,36 multiplizieren und 132,16 erhalten und das auf 133 aufrunden, klarstellen müssen, dass Sie dies für einen Fehler / Fehler halten, den sie brauchen reparieren. Vielleicht spielt es keine Rolle, wie oder warum sie auf die falsche Antwort gekommen sind, solange die nächste Version der Software die richtige Antwort liefert. Ich weiß nicht, wie schwer es ist, dieses Produkt dazu zu bringen, diese Mathematik durchzuführen, aber Sie sollten es für viele verschiedene Werte testen, um zu sehen, ob es immer die erwartete Antwort erhält, oder noch besser, wenn möglich, den Codeabschnitt extrahieren lassen, der die Mathematik durchführt und isoliert gegen eine lange Liste von Operanden validieren. Oder sogar so angeben, die Software muss in der Lage sein, das erwartete Ergebnis für diese Liste von Operanden und Antworten zu erhalten.

Eine einfache Lösung besteht darin, einfach die Hälfte von Ihrem Mikrocontroller-Ergebnis abzuziehen.

Aus deinem Beispiel:

56 * 2,36 = 132,16 Runden zu 133

Dann

(56 * 2,36) - 0,5 wird auf 132 gerundet

Das ist in dem gegebenen Beispiel in Ordnung, aber Sie können das im Allgemeinen nicht anwenden, ohne zu wissen, welche Rundungsmethode verwendet wurde.
Nun, es scheint, als würde es aufrunden, also wäre dies dann eine gültige Lösung
Aufrunden passiert nicht einfach, man muss bewusst handeln, höchstwahrscheinlich 0,5 addieren...
Ich glaube nicht, dass der Poster die Kontrolle über den Code hat.
@Cybergibbons - du hast recht, ich habe keine Kontrolle über den Code.