Optimierung Berechnungen

Hallo zusammen,

ich habe aktuell ein paar Kalkulationen, die auch soweit funktionieren.
Allerdings gab/gibt es teilweise Rundungsprobleme und Optimal ist bestimmt auch etwas anderes.

Vielleicht könnt ihr mir etwas verständlicher machen, wo ich zur Verbesserung ansetzen kann:

const uint16_t Factor = 256;
uint8_t response[10];
GetResponse(response);

//Drehzahl (0-16.000)
uint32_t value;
value = (((uint32_t)response[1] * Factor) + (uint32_t)ecuResponse[2]) * 100 / Factor;
BT.println(value);

//Druck
value = (uint32_t)response[3] * 190*5/Factor/Factor;
BT.println(value);

//Temperatur -40 - +215
int value2 = ((int)response[4] - 30) * 160 / Factor;
BT.println(value2);

Wie man sieht, erhalte ich Werte von 0-255. Ist dieser >255, so setzt sich die Berechnung immer aus byte1*256+byte2 zusammen.
Jede Berechnung erfolgt dann mit einem Faktor, der in Dezimal vorliegt. Um dem aber zu entgehen, habe ich alle Faktoren wieder auf die Basis 256 gebracht:
Statt: 3,7109375
Besser: (190*5/256)

Damit bleibe ich dann (meist) im positiven Ganzzahl-Bereich. Jedoch in einem sehr großen, wie ich befürchte.

Ist da überhaupt noch was für den Arduino zu verbessern?
(256*a+b) * 5/4/256
Könnte ich doch auch so machen:
((a << 8 ) + b) * 5 / 4 / 256
Ist das unnütze Mikrooptimierung?

Für den bekannten Stubs in die richtige Richtung wäre ich Euch dankbar :slight_smile:

Ist da überhaupt noch was für den Arduino zu verbessern?
(256*a+b) * 5/4/256
Könnte ich doch auch so machen:
((a << 8) + b) * 5 / 4 / 256
Ist das unnütze Mikrooptimierung?

Ich habe es nicht nachgeprüft, aber ich würde davon ausgehen, dass der Compiler diese Optimierung sowieso macht.

Er dürfte sogar das “/ 4 / 256” durch ein " >> 10" ersetzen. Bei simplen Berechnungen mit konstanten Werten kann der Compiler relativ gut optimieren und macht das in den meisten Fällen auch.

Danke, dann muss ich also nur darauf achten, dass die erste Berechnung in den passenden Datentyp gewandelt wird und den Rest macht prinzipiell der Compiler.

Tu mich immer noch ein bisschen schwer binär zu denken und statt * 256 << 8 oder / 256 >> 8 zu verwenden.
Wenn der Compiler das bereits macht, ist es mir nur recht :slight_smile:

Ja, Multiplikation / Division mit konstanten Zweierpotenzen ersetzt der Compiler durch Bitshifting.

Muss also nicht explizit geschrieben werden und erhöht somit die Lesbarkeit des Codes.

Wenn es Berechnungen mit anderen Faktoren / Dividenden sind, lohnt sich dagegen die manuelle Zerlegung in schnelle Shifts, wenn die Funktion zeitkritisch ist.

LG, Helmuth

Ja, das Problem hatte ich mal mit einem Chef vor ca. 25 Jahren.

Da hatten wie eine Vorverarbeitung auf einem 8-Bitter mit 256 Byte RAM in ASM. (CrossASM auf Fremdsystem)

12 Messwerte einlesen, die beiden höchsten und die beiden niedrigsten Werte rauswerfen und dann die Summe durch 8 teilen.
Der wollte ewig nicht begreifen, warum ich nicht 14 Messwerte nehme und durch 10 teile ("so rechnet doch die ganze Welt"), sondern durch 8 --> eben weil das mit shift schneller und RAM-schonender ging.

Gruß Tommy

Wenn der Compiler das bereits macht, ist es mir nur recht

Am Rande:
Viele AVR(alle?) haben einen Hardware Multiplizierer eingebaut.
Das macht die integer Multiplikation recht billig und schnell.

Aber keine eingebaute Hardware Division.
Die ist somit recht teuer. (falls keine konstanten 2er Potenzen vorliegen)