für ein kleines Projekt muss ich Wägewerte von einer Waage in ein anderes Format übertragen. Die Variable String gewicht soll dabei um eine Nachkommastelle gekürzt und mit Nullen vorne aufgefüllt werden. Soweit so gut.
Wenn ich das untere Testprogramm ausführe, dann klappt es eigentlich, aber wenn als letzte Nachkommastelle eine 5 steht, dann rundet Serial.print(Test_Double, 4) oder dtostrf(Test_Double, min_width, 4, str) die Zahl ab statt aufzurunden.
Der Output sieht wie folgt aus:
String Before Conversion: +24.12745
String mit print formatiert: 1+0024.1274
String mit dtostrf: 1+0024.1274
#define BUFFER_SIZE 30
// Variablen zum speichern der Werte
char str[30];
int min_width;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
String gewicht = "+24.12745";
Serial.print("String Before Conversion: ");
Serial.println(gewicht); // string before conversion to double
double Test_Double = gewicht.toDouble();
String a1 = "1+00";
Serial.print("String mit print formatiert: ");
Serial.print(a1); // string After conversion to double
Serial.println(Test_Double, 4);
Serial.print("String mit dtostrf: ");
Serial.print(a1);
min_width = 5;
dtostrf(Test_Double, min_width, 4, str);
//sprintf(str, "Gewicht %.4d\n", Test_Double);
Serial.println(str);
}
void loop() {
// put your main code here, to run repeatedly:
}
Wie kann ich erreichen, dass das Programm bei einer 5 aufrundet und nicht abrundet? Wenn ich als Teststring +24.127451 verwende, dann wird dei Zahl aufgerundet.
Könnte sein, dass dieser Text zu 24.1274499... gewandelt wird wenn das die nächstgelegene Float-Zahl ist. Die wird dann tatsächlich richtigerweise als 24.1274 dargestellt.
Bei kleinen Arduinos hat double übrigens nur 32 bit, genau wie float
Ich sehe das Problem in der geringen Genauigkeit der Float-Zahlen. Je anch zahl gibt es nur zwischen 6 und 7 "richtige" Ziffern.
Vieleicht hilft fp64lib - Arduino Reference
Grüße Uwe
ich wusste nicht, dass double und float bei Arduino beide mit 32 bit arbeiten.
Ich werde mir wie hier beschrieben, https://www.mikrocontroller.net/articles/Festkommaarithmetik, die Rundungsfunktion in meine Funktion einbauen, die die letzte Nachkommastelle rundet.
Die Anzahl der Nachkommastellen ist immer gleich. Ich muss von 5 Nachkommastellen auf 4 Nachkommastellen runden.
Das was mir zu gute kommt ist, dass ich mit den Zahlen nicht rechnen muss und einfach als String über die serielle Schnittstelle weiterleite.
/**
*
* format_gewicht(String &g)
*
* Diese Funktion wird aufgerufen, um das Datenformat der KERN Analysewaage auf die Basiseinheit anzupassen
* Im Array werden die zu entfernenden Zeichen definiert
*
* \param &g Das Gewicht wird als String per Referenz übergeben
* \retval Gewicht als Double
**/
double format_gewicht(String &g) {
String zeichen[] = { " ", "[", "]", "g", "S" };
for (int i = 0; i < (sizeof(zeichen) / sizeof(zeichen[0])); i++) // sizeof(zeichen / sizeif(zeichen[0]) - sizeof() gibt die komplette Zahl der bytes des Arrays zurück.
{ // Wir müssen dann durch den Datentyp dividieren
g.replace(zeichen[i], ""); // löscht unnoetige Zeichen
}
uint8_t string_laenge = g.length() - 1; // \n Zeichen wird ignoriert
uint8_t i;
// letzte Stelle runden
if (g[string_laenge] >= '5') {
for (i = (string_laenge - 1); i >= 0; i--) {
g[i] += 1; // Aufrunden
if (g[i] <= '9')
break; // kein Übertrag, schleife verlassen
else
g[i] = '0'; // Übertrag und Überlauf
}
}
return g.toDouble(); // wird eventuell nicht mehr benoetigt
}
@uwefed Ich habe mir die fp64lib angeschaut und wollte es sofort benutzten. Leider konnte ich mit Serial.print() die Zahl nicht ausgeben. Ich werde mir nochmal die Libray für zukünfitge Projekte genauer anschauen.
Ob dir das "zu gute kommt" weiß ich nicht, genaugenommen ist es bei dir auch kein mathematisches Runden, sondern eher Textverarbeitung.
Und die Frage, ob eine dargestellte Ziffer "5" auf- oder abzurunden ist, liegt prinzipiell nicht an float64 / float32, kann aber im Einzelfall tatsächlich unterschiedlich sein.
Wenn du 0,44445 auf 4 Stellen rundest und da 0,4445 erwartest, kannst du das Ganze nochmal machen und auf 3 Stellen gerundet fälschlich 0,445 bekommen, obwohl 0,444 richtig wäre.
da hast du recht. Würde zweimal den String so runden, hätte ich ein falsches Ergebnis. Aber der Wägewert wird nur weitergeleitet und nachdem ich es weitergeleitet habe, wird der String gelöscht.