Forum: Mikrocontroller und Digitale Elektronik zwei float-Zahlen vergleichen / 1..2 Nachkommastellen


von epika (Gast)


Lesenswert?

Hallo,

wie vergleiche ich am einfachsten zwei Float-Zahlen aber nur bis zur 
ersten oder zweiten Nachkommastelle?
1
float temp;
2
float lastTemp;
3
...
4
...
loop:
1
if(temp != lastTemp){
2
...
3
...
4
...
5
lastTemp = temp;
6
}

Danke

von Werner (Gast)


Lesenswert?

Mit 100 multiplizieren und als int vergleichen.

von Klaus W. (mfgkw)


Lesenswert?

Kann man, wenn es vom Wertebereich her passt.

Wenn es geht, drängt sich der Verdacht auf, ob es nicht gleich besser 
wäre alles in ganzen Zahlen zu rechnen (oder Festkomma) - das war aber 
nicht gefragt zugegebenermaßen.

Ansonsten sowas wie fabs( a - b )<0.01...

von epika2 (Gast)


Lesenswert?

Werner schrieb:

> Mit 100 multiplizieren und als int vergleichen.

irgendwie so?:
1
if( ( (int)temp*100 ) !=  ( (int)lastTemp*100 ){
2
3
}

hm, muss wohl mal den float typ studieren, vielleicht geht es mit so 
einem bit shift operator ....

von Tim T. (tim_taylor) Benutzerseite


Lesenswert?

epika2 schrieb:
> Werner schrieb:
>
>> Mit 100 multiplizieren und als int vergleichen.
>
> irgendwie so?:
>
1
> 
2
> if( ( (int)temp*100 ) !=  ( (int)lastTemp*100 ){
3
> 
4
> }
5
>
>
> hm, muss wohl mal den float typ studieren, vielleicht geht es mit so
> einem bit shift operator ....

Sinnvoller wäre es beim Zuweisen von temp und damit wohl auch indirekt 
bei lastTemp direkt auf (unsigned) int oder short zu gehen, oder 
brauchst du das irgendwo wirklich als float?

https://www.mikrocontroller.net/articles/Festkommaarithmetik

: Bearbeitet durch User
von Erich (Gast)


Lesenswert?

epika2 schrieb:
> if( ( (int)temp*100 ) !=  ( (int)lastTemp*100 ){

So ähnlich, aber mit Rundung
  if( (int)(temp*100 + 0.5 ) !=  (int)(lastTemp*100 + 0.5 ) {

von Rolf (Gast)


Lesenswert?

Erich schrieb:
> epika2 schrieb:
>> if( ( (int)temp*100 ) !=  ( (int)lastTemp*100 ){
>
> So ähnlich, aber mit Rundung
>   if( (int)(temp*100 + 0.5 ) !=  (int)(lastTemp*100 + 0.5 ) {

Die Klammerung stimmt nun schon mal, aber die Rundung funktioniert so 
nur für positive Zahlen.

Der TO wollte eine Temperatur bis zur 2. Nachkommastelle vergleichen, da 
ist eine Rundung von tausendstel auf hundertstel Grad sicherlich nicht 
notwendig.

von Tim T. (tim_taylor) Benutzerseite


Lesenswert?

Rolf schrieb:
> Erich schrieb:
>> epika2 schrieb:
>>> if( ( (int)temp*100 ) !=  ( (int)lastTemp*100 ){
>>
>> So ähnlich, aber mit Rundung
>>   if( (int)(temp*100 + 0.5 ) !=  (int)(lastTemp*100 + 0.5 ) {
>
> Die Klammerung stimmt nun schon mal, aber die Rundung funktioniert so
> nur für positive Zahlen.
>
> Der TO wollte eine Temperatur bis zur 2. Nachkommastelle vergleichen, da
> ist eine Rundung von tausendstel auf hundertstel Grad sicherlich nicht
> notwendig.

Diese Rundung macht auch sonst keinen Sinn...

von Klaus W. (mfgkw)


Lesenswert?

Erich schrieb:
> So ähnlich, aber mit Rundung
>   if( (int)(temp*100 + 0.5 ) !=  (int)(lastTemp*100 + 0.5 ) {

Bevor ich zweimal in float addiere und multipliziere und nach int 
konvertiere, nur um dann rasend schnell ganzzahlig zu vergleichen), habe 
ich doch die Differenz in float gleich schneller berechnet...

von MaWin (Gast)


Lesenswert?

Klaus W. schrieb:
> Ansonsten sowas wie fabs( a - b )<0.01...

Die schlaueste Lösung, kommt auch mit Rundungsfehlern klar.

von Tim T. (tim_taylor) Benutzerseite


Lesenswert?

MaWin schrieb:
> Klaus W. schrieb:
>> Ansonsten sowas wie fabs( a - b )<0.01...
>
> Die schlaueste Lösung, kommt auch mit Rundungsfehlern klar.

Nein, die schlaueste Lösung ist und bleibt das Problem nicht mit Floats 
zu lösen.

von A. S. (Gast)


Lesenswert?

Erich schrieb:
> So ähnlich, aber mit Rundung
>   if( (int)(temp*100 + 0.5 ) !=  (int)(lastTemp*100 + 0.5 ) {

Nur um es für den TO deutlich zu machen (obwohl es andere schon gesagt 
haben):

Runden ist niemals sinnvoll für einen Vergleich. Weder implizit durch 
Wandlung auf int noch explizit per round.

Die einzige wirksame Methode ist jene von Klaus: Test ob die Differenz 
kleiner als erlaubt ist.

von epika (Gast)


Lesenswert?

Tim T. schrieb:
> brauchst du das irgendwo wirklich als float?

bei der Anzeige der Temperatur, ja:
1
.print(temp,1);

folgender Code funktioniert irgendwie nicht, auch nicht bei positiven 
Werten
1
if( ((int)temp*100+0.5) !=  ((int)lastTemp*100+0.5) ){

das mit fabs() kenne ich nicht, muss ich mir mal anschauen.

vielen Dank

von Klaus W. (mfgkw)


Lesenswert?

epika schrieb:
> folgender Code funktioniert irgendwie nicht, auch nicht bei positiven
> Werten
> if( ((int)temp*100+0.5) !=  ((int)lastTemp*100+0.5) ){

Hier machst du aus temp erst eine int (dann sind die Nachkommastellen 
weg!), dann multiplizierst du mit 100 . davon kommen die 
Nachkommastellen nicht zurück.
Dann noch wieder in float 0.5 zu addieren, ist sinnlos, aber auch schon 
egal, ebenso wie der Rest.

von Dirk B. (dirkb2)


Lesenswert?

epika schrieb:
> Tim T. schrieb:
>> brauchst du das irgendwo wirklich als float?
>
> bei der Anzeige der Temperatur, ja:
>
1
> .print(temp,1);

Auch da nicht.
Man kann auch mit Cent rechnen und trotzdem Euro ausgeben - ohne float.

> folgender Code funktioniert irgendwie nicht, auch nicht bei positiven
> Werten
>
1
> if( ((int)temp*100+0.5) !=  ((int)lastTemp*100+0.5) ){

Achte auf die Klammerung!

> das mit fabs() kenne ich nicht, muss ich mir mal anschauen.

unbedingt.

: Bearbeitet durch User
von Roland F. (rhf)


Lesenswert?

Hallo,
epika schrieb:
> das mit fabs() kenne ich nicht, muss ich mir mal anschauen.

Du bildest die Differenz beider Werte. Das Ergebnis kann positiv, 
negativ oder null sein. Interessant ist aber nur der Betrag also der 
absolute Wert, den du mit fabs() bildest. Diesen Betragswert vergleichst 
du jetzt mit einem "Genauigkeitswert" (wird meist als epsilon 
bezeichnet). Ist der Betragswert gleich oder kleiner als der 
"Genauigkeitswert", gelten die ursprünglichen Werte als gleich.
Wie genau die beiden Werte übereinstimmen müssen um als gleich zu 
gelten, kannst du mit dem "Genauigkeitswert" vorgeben. Je kleiner dieser 
Wert ist desto genauer stimmen die ursprünglichen Werte überein.

rhf

von Tim T. (tim_taylor) Benutzerseite


Lesenswert?

epika schrieb:
> Tim T. schrieb:
>> brauchst du das irgendwo wirklich als float?
>
> bei der Anzeige der Temperatur, ja:
>
1
> .print(temp,1);
2
>

Nein, auch da kannst du als Int ausgeben und das Komma einfach an die 
richtige Stelle setzen.

> folgender Code funktioniert irgendwie nicht, auch nicht bei positiven
> Werten
>
1
> if( ((int)temp*100+0.5) !=  ((int)lastTemp*100+0.5) ){
2
>

Der Code ist auch Unsinn, lass die unsinnige Rundung weg.

> das mit fabs() kenne ich nicht, muss ich mir mal anschauen.
>
> vielen Dank

fabs macht eigentlich nichts anderes als:
1
float fabs(float a) {
2
    if (a < 0) return -a;
3
    return a;
4
}

von PittyJ (Gast)


Lesenswert?

Ich habe auch viel mit Temperaturen zu tun. Deshalb rechne ich intern 
nur in Zehntel Grad als Integer.
Die Genauigkeit reicht in der Anwendung.
Das erspart Rechnerei, insbesondere auf Controllern ohne FPU.
Nur bei der Ausgabe auf Bildschirm muss dann etwas gemacht werden. und 
das würde auch nur mit Mod und Div gehen.

von Klaus W. (mfgkw)


Lesenswert?

Tim T. schrieb:
> fabs macht eigentlich nichts anderes als:

Genau genommen macht fabs() das mit doubles.
Das fabs() für float heißt fabsf()...

(Wenn man es nicht verwirrend machen würde, könnte es ja jeder.)

: Bearbeitet durch User
von Tim T. (tim_taylor) Benutzerseite


Lesenswert?

Klaus W. schrieb:
> Tim T. schrieb:
>> fabs macht eigentlich nichts anderes als:
>
> Genau genommen macht fabs() das mit doubles.
> Das fabs() für float heißt fabsf()...

Stimmt, hast recht.

> (Wenn man es nicht verwirrend machen würde, könnte es ja jeder.)

Könnte da noch
1
float fabsf(float a) {
2
    return a < 0 ? -a : a;
3
}
anbieten, aber auch da ist es eigentlich schon zu leicht.

von Bauform B. (bauformb)


Lesenswert?

epika schrieb:
> Tim T. schrieb:
>> brauchst du das irgendwo wirklich als float?
>
> bei der Anzeige der Temperatur, ja:
1
.print(temp,1);

Das heißt, du hast ein eigenes print, das Nachkommastellen kennt? Dann 
gibt es doch garkeinen Grund mehr für float. Für den Zweck hab' ich mein 
printf aufgebohrt. Für 2 Kommastellen sieht das so aus ;)
1
printf ("%6.2d", adc_to_celsius (adc, 100));

von Tim T. (tim_taylor) Benutzerseite


Lesenswert?

Bauform B. schrieb:
> Das heißt, du hast ein eigenes print, das Nachkommastellen kennt? Dann
> gibt es doch garkeinen Grund mehr für float. Für den Zweck hab' ich mein
> printf aufgebohrt. Für 2 Kommastellen sieht das so aus ;)
1
printf 
2
> ("%6.2d", adc_to_celsius (adc, 100));

Mal eben aus dem Rückenmark:
1
void print_temp( int temp ) {
2
    int vorkomma = temp / 100;
3
    int nachkomma = temp - 100 * vorkomma;
4
    
5
    printf("%d,%02d", vorkomma, abs(nachkomma));
6
}

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.