Go Down

Topic: Nachkommastellen bei float (Read 4675 times) previous topic - next topic

hk007

Hi,
jetzt komm ich mal wieder nicht weiter. Vllt. steh ich ja auch auf dem Schlauch.  :)
Ich lese mit der DallasTemperature-Lib einige 1820er aus.
Code: [Select]

...
   float TempFloat[7];
   TempFloat[1] = sensors.getTempC(Sensor1);
   Serial.println (TempFloat[1]);
...


Ich sehe dann Werte wie "22.50" im Serial Monitor. Auf dem LCD ist es genauso.
Wieso wird die Float auf genau 2 Nachkommastellen ausgegeben? Woher hat das Programm die Informationen? Er könnte ja auch "22.500" schreiben.
Warum frage ich das:
Zum einen, weils mich interessiert.  :P
Zum anderen, weil ich die zweite Nachkommastelle als überflüssig sehe. Wenn ich mit 9 Bit Auflösung einlese, dann hab ich eh nur 0,5° Schritte.
Und da reicht mir dann eine Nachkommastelle. Kann ich das meiner float beibringen, daß die nur "22,5" speichert? Und dann bei der Ausgabe ohne SPRINTF o.ä. den Wert ausgibt?

gruß/hk007







Arduino 1.0.5 | Arduino UNO & MEGA | Arduino 1.54r2 mit DUE

uwefed

http://arduino.cc/en/Serial/Print

also einfach:
Serial.println (TempFloat[1],1);

Default sind 2 Nachkommastellen, man kann aber angeben wieviel man will.
Grüße Uwe

hk007

Ja genau, das ist die Lösung. Und so einfach. Und ich hab noch nie davon gehört. [SCHÄM]
Und v.a.: Funktioniert auch mit LCD-Ausgabe und auch mit client.print für den Webserver.

Danke dir!!
Arduino 1.0.5 | Arduino UNO & MEGA | Arduino 1.54r2 mit DUE

uwefed

Bitte.
Müßte überall funktionieren wo xx.print steht.
Uwe

Serenifly

Nein. Float hat nur 4 Byte. Für höhere Genauigkeit bräuchte man einen 8 Byte Floating Point Datentyp. Das gibt es nur auf dem Due.

michael_x


benötige um die 10 Nachkommastellen!
...
Für höhere Genauigkeit bräuchte man einen 8 Byte Floating Point Datentyp


Glaub ich nicht. ;)

1.23456 * 10 -10  geht natürlich locker mit simplen 4 byte floats.
Das kannst du dann auch als 0.0000123456 mit 10 Nachkommastellen schreiben.
Serial.print ( mySmallFloat, 10); // wenns den so unleserlich sein soll.

10 Dezimalziffern Genauigkeit brauchst du vermutlich nicht.

uwefed



benötige um die 10 Nachkommastellen!
...
Für höhere Genauigkeit bräuchte man einen 8 Byte Floating Point Datentyp

Glaub ich nicht. ;)

Glaub ich schon. Mehr als 6-7 signifikante stellen sind bei 4 Byte-Float nicht drin. Es sei denn Du willst Hausnummern ausgeben.
Grüße Uwe

michael_x

Quote
Mehr als 6-7 signifikante stellen sind bei 4 Byte-Float nicht drin.

Vollkommen klar, Uwe. Mir gings darum dass "ich benötige 10 Nachkommastellen" vermutlich nicht viel mit einer Genauigkeit jenseits eines float32 zu tun haben. ( ausser Schnix überzeugt mich, wofür er das braucht ).

6 bis 7 signifikante Dezimal-Stellen kann man nicht mit einem Sensor messen. Das wäre eine Genauigkeit von
0,0001 % .

jurs


Quote
Mehr als 6-7 signifikante stellen sind bei 4 Byte-Float nicht drin.

Vollkommen klar, Uwe. Mir gings darum dass "ich benötige 10 Nachkommastellen" vermutlich nicht viel mit einer Genauigkeit jenseits eines float32 zu tun haben. ( ausser Schnix überzeugt mich, wofür er das braucht ).


Die 6-7 signifikanten Stellen wiegen manche Programmierer in eine trügerische Sicherheit. Mit "float" Zahlen zu rechnen kann schon bei nur 3 signifikanten Stellen in der Zahl zu falsche Ergebnissen führen, also z.B. beim Rechnen mit einstelligen(!) Zahlen und zwei Nachkommastellen.

Anbei mal ein kleiner Test-Sketch. Mit "float" können teilweise nicht mal Zahlen unter 10 mit zwei Stellen nach dem Komma korrekt zusammengerechnet werden. Durch die interne Speicherung als "float" geht sofort Genauigkeit verloren. Und wenn man dann zwei kleine Rechenergebnisse vergleicht, kann man sich nur wundern.

Seht selbst:
Code: [Select]


// Spass mit float by 'jurs' for German Arduino forum
void setup()
{
  Serial.begin(9600);
  float a=1.31, b=1.62, c=1.11, d=1.82;
  Serial.println("Float-Zahlen mit 2 Nachkommastellen dargestellt:");
  Serial.print("a= ");Serial.println(a,2);
  Serial.print("b= ");Serial.println(b,2);
  Serial.print("c= ");Serial.println(c,2);
  Serial.print("d= ");Serial.println(d,2);
  Serial.println();
  Serial.println("Dieselben Zahlen mit 8 Nachkommastellen:");
  Serial.print("a= ");Serial.println(a,8);
  Serial.print("b= ");Serial.println(b,8);
  Serial.print("c= ");Serial.println(c,8);
  Serial.print("d= ");Serial.println(d,8);
  Serial.println();
  if (a+b == c+d)
    Serial.println("a+b ist gleich c+d");
  else
    Serial.println("a+b ist NICHT gleich c+d");
  Serial.println();
  Serial.print("a+b= ");Serial.println(a+b,8);
  Serial.print("c+d= ");Serial.println(c+d,8);
}

void loop() {
}


michael_x

Richtig, aber das würde mit double nicht wirklich besser
( bräuchte nur mehr Ziffern um das gleiche zu sehen),
daher ist es kein Mangel, dass ein Arduino keine double hat...

uwefed

#10
Nov 04, 2013, 08:35 pm Last Edit: Nov 04, 2013, 08:45 pm by uwefed Reason: 1

Quote
Mehr als 6-7 signifikante stellen sind bei 4 Byte-Float nicht drin.

Vollkommen klar, Uwe. Mir gings darum dass "ich benötige 10 Nachkommastellen" vermutlich nicht viel mit einer Genauigkeit jenseits eines float32 zu tun haben. ( ausser Schnix überzeugt mich, wofür er das braucht ).

6 bis 7 signifikante Dezimal-Stellen kann man nicht mit einem Sensor messen. Das wäre eine Genauigkeit von
0,0001 % .

ok, über die Notwendigkeit des Genauigkeitsextremismus läßt sich zweifeln.
Grüße Uwe

michael_x

Quote
Jedesmal wenn ich mehr als 6 Zahlen in meinem Terminalprogramm eingegeben habe, kam die ERROR Funktion zum Tragen


heisst das, dass
if (eingabe.startsWith(REF)) nicht true ergab, sondern in den else Zweig lief ?

Dann schau/zeig doch erstmal, was eingabe ist und welchen Wert es hat (und warum es nicht mit "REF" anfängt)

Dass du keine String Objekte verwenden sollst, werden wir dir unabhängig von deinem Problem um die Ohren hauen ;) ...

jurs


ich kann halt nur REF Leerzeichen und  dann 7 Zahlen (incl. Dezimalpunkt) eingeben.
Ab 8 Zahlen kommt die else zum Tragen.
Wenn ich meinen String statt REF nur RE nenne sind es 8 gültige Zahlen.
Kann der serielle Monitor nur eine bestimmte String Länge einlesen?


Wenn Du mal zurückblätterst: Vor nicht allzu langer Zeit hatte ich Dir für den Sketch, um den es Dir offenbar immer noch geht, einen Democode gesendet, in dem diese Zeile mit Kommentierung drinstand:

Code: [Select]

delay(100); // warten bis alle Zeichen im Eingangspuffer


Ein delay(100) reicht bei einer Baudrate von 9600 aus, um fast 100 Zeichen einlesen zu können.
Kalkulierst Du zu knapp, funktioniert diese Art Einleseroutine nicht mehr, wenn die Eingabe zu lang wird.

Go Up