mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Aus einem "int" ein "float" erzeugen


Autor: Stefan KM (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zuammen.

Ich möchte gern aus einem int (2Byte) ein float mit zwei 
Nachkommastellen erzeugen.
Der int Wert stellt eine Temperatur dar, wobei im High Byte die 
Temperatur steht mit Vorzeichen(Bit7) und im Low Byte die 
Nachkommastelle.

Mein Frage ist nun, wie kann ich daraus eine float Zahl erzeugen mit dem 
entsprechenden Wert z.B. 20,34°C?

Habe folgendes durchgeführt, was nicht funktioniert:

float Get_Temp()
{
 float temperature;               // Ergebnis
 float temp0;                     // low byte
 float temp1;                     // high byte

 temp0 = MeasValues.Temperature%256;
 temp1 = MeasValues.Temperature/256;

 temperature=temp0/100;           // low byte wird durch 100 geteilt
 temperature += temp1;            // und zum high byte dazu addiert

 return temperature;              // Rückgabe.
}


Weiß jemand ob ich da einen Fehler gemacht habe?

Danke für Eure Hilfe
Stefan

Autor: PM (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mmmm,
bin mir jetzt nicht sicher ob ich das richtig verstanden habe.

Aber wenn im high Byte Vorkomme und im lowe Byte Nachkomme steht, würd 
ich das einfach so machen (int mit den Werten ist temp) :

[c]
float temperatur=0;

temperatur = (float) ((temp & 0xFF00)>>8) + ((float) (temp & 
0x00FF))/100;
[/]

Gruß
Philipp

Autor: Michael K. (mmike)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Probier mal:

float temperature = (char)(MeasValues.Temperature >> 8); // Vor dem 
Komma
temperature += (float)(((char)MeasValues.Temperature) / 100.0f); // Nach 
dem Komma ....
Grüße Michael

Autor: PM (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
sorry, nicht richtig gelesen...

einfach tamp mit MeasValues.Temperature ersetzen...

Autor: Michael K. (mmike)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
vertippt ....
temperature += (float)((char)MeasValues.Temperature) / 100.0f;

Autor: Ingo Elsen (ogni42)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So vielleicht:
float Get_Temp(int16_t tempIn)
{
 float temperature;

 temperature = (float)(tempIn>>8); // vorkomma
 tempIn &= 0xff; // HighByte zu Null setzen
 temperature += (float)(tempIn)/256.0; //Nachkomma

 return temperature; 
}

  

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gibt es irgendeinen triftigen Grund, das in float zu machen? Wofür wird 
der Rückgabewert denn überhaupt benötigt? So was (v.a. bei nur zwei 
Nachkommastellen) macht man in Festpunkt. Oder hast Du zu viel 
Rechenleistung?

Autor: Stefan KM (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich brauche die Nachkommastelle für die Anzeige auf einem Display. es 
würde auch eine Nachkommastelle reichen.

Habe alle von euch genannten Varianten probiert. Es wird immer nur 26.00 
angezeigt.

Autor: Stefan KM (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Könnte es ein Problem mit der sprintf Anweisung sein?
Sieht wie folgt aus:

sprintf(Buffer,"%.1f °C",temperature);

Danke euch schon mal für due Hilfe

Autor: Philipp Burch (philipp_burch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
rofl

Es wäre wohl sinnvoller, du würdest die Ausgabe entsprechend anpassen, 
damit zuerst der Vorkommaanteil, dann das Komma und zuletzt der 
Nachkommaanteil ausgegeben wird. Für sowas braucht man ganz bestimmt 
keinen Float.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Ich brauche die Nachkommastelle für die Anzeige auf einem Display.
Das hab ich befürchtet! Weißt Du, was ein µC für Verrenkungen machen 
muss, um mit Gleitkommazahlen zu rechnen?

Wenn Du den Wert nur brauchst, um ihn auf einem Display o.ä. auszugeben, 
einfach die ganze Rechnung in hundertstel Grad durchführen (als 
Ganzzahl!) und bei der Ausgabe das Dezimaltrennzeichen an der richtigen 
Stelle einbauen. Ist 100mal schneller als ne float-Berechnung. Und das 
mit dem sprintf ist auch nur Ressourcenverschwendung. Die Rechnung und 
das Speichern als String kann man in einem Arbeitsgang machen.

Autor: Stefan KM (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Leider habe ich Text mit variabler Breite verwendet. Dies führt dazu, 
dass ich den Punkt jedesmal mit verrücken müßte. Und das ist so gut wie 
unmöglich, weil viel zu aufwendig.

Aber trotzdem danke.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Verstehe echt nicht, warum alle Leute immer meinen, alles in Gleitkomma 
rechnen zu müssen. Und dann wundern sie sich, wenn erstens das Ergebnis 
nicht dem entspricht, was sie sich vorstellen und zweitens dass der 
komplette Speicher und ne Menge Rechenzeit für die popelige Berechnung 
draufgeht...

Autor: Stefan KM (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und wie ?

Autor: Stefan KM (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Johannes.
Wie soll das mit der Berechnung und der Speicherung als String 
funktionieren?

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan KM wrote:
> Leider habe ich Text mit variabler Breite verwendet. Dies führt dazu,
> dass ich den Punkt jedesmal mit verrücken müßte. Und das ist so gut wie
> unmöglich, weil viel zu aufwendig.
??? Muss ich das jetzt verstehen ???

Wenn Du die Temperatur als ganzzahligen Wert (integer) vorliegen hast, 
dann musst Du nur sukzessive durch 10 teilen, den Rest jeweils in eine 
Stelle des Zielarrays schreiben (vorher 0x30 addieren, dann steht da 
schon direkt das entsprechende ASCII-Zeichen), das Dezimaltrennzeichen 
an die richtige Stelle (auch gleich als ASCII-Zeichen) und das °C 
dahinter ändert sich ja vermutlich nicht. Das ist die ganze Prozedur. 
Kostet kaum Ressourcen, geht Ruckzuck und führt v.a. zum gewünschten 
Ergebnis!

Autor: Michael K. (mmike)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Probier mal:

sprintf(Buffer,"%d,%d °C", (char)(MeasValues.Temperature >> 8),
                           (char)(MeasValues.Temperature & 0xFF));

Was wird dann angezeigt ?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan KM wrote:
> Ich brauche die Nachkommastelle für die Anzeige auf einem Display. es
> würde auch eine Nachkommastelle reichen.
>
> Habe alle von euch genannten Varianten probiert. Es wird immer nur 26.00
> angezeigt.

Bei welchen Eingangswerten?
Wie sehen denn die beiden Integer dafür aus?

Autor: Stefan KM (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Johannes

Wie fange ich den Rest auf?

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan KM wrote:
> @ Johannes.
> Wie soll das mit der Berechnung und der Speicherung als String
> funktionieren?
Das, was Du machen musst, ist im Prinzip dasselbe, was sprintf auch 
machen würde. Nur ist sprintf eine eierlegende Wollmilchsau und bringt 
viel zu viel Funktionalität mit, die Du gar nicht brauchst, die aber 
Speicherplatz belegt. Das selbe gilt für die Gleitkomma-Bibliothek.

Wenn Du, wie oben angedeutet, Deinen Temperaturwert als integer hast, 
dann musst Du den eben in einzelne Dezimalstellen zerlegen und als 
ASCII-Zeichen speichern.

Um auf Dein Beispiel mit 20,34 °C zurückzukommen: Verarbeite den 
Ausgangswert so, dass Du für 20,34°C die Zahl 2034 in dem integer stehen 
hast (also den Wert in hundertstel °C). Jetzt musst Du sukzessive diese 
Zahl immer wieder durch 10 dividieren und den Rest (entweder mit Modulo 
ermitteln oder gleich die Bibliotheksfunktion div aus der stdlib.h 
verwenden, die liefert Ergebnis und Rest direkt zurück) speichern. 
Dadurch kriegst Du (von hinten angefangen) die Dezimalstellen. Das sind 
dann Ziffern von 0...9. Die ASCII-Zeichen für die Ziffern sind 
0x30...0x39. Man muss also nur zu der Zahl 0x30 addieren, und schon hat 
man das entsprechende ASCII-Zeichen. Dann nach der zweiten Stelle von 
hinten den Punkt oder das Komma einbauen und schon ist der String fast 
fertig. Das "°C" und der Nullterminator können ja fest bleiben.

Autor: Stefan KM (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
QJohannes.

danke für den Tip. Probier ich morgen aus. Hab jetzt leider keine Zeit 
mehr.

Trotzdem danke.

Stefan

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan KM wrote:
> danke für den Tip. Probier ich morgen aus.
Gut.

> Hab jetzt leider keine Zeit
> mehr.
Dito...

> Trotzdem danke.
Bittesehr. Schau Dich aber auch mal im Forum um. Das Thema mit 
"Zahlenwert -> ASCII-String" hatten wir schon oft.

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Johannes M. wrote:
> (entweder mit Modulo ermitteln oder gleich die Bibliotheksfunktion div aus
> der stdlib.h verwenden, die liefert Ergebnis und Rest direkt zurück)

Als ich solche Berechnungen ausgeführt hab, habe ich Modulo und den 
stinknormalen / Operator in zwei aufeinanderfolgenden Schritten direkt 
hintereinander benutzt (Natürlich mit den gleichen Operanden).

Der Compiler hat daraus einen Funktionsaufruf gemacht. Nämlich eben die 
div Funktion aus der stdlib :-). Brauchst du dich also nicht drum 
kümmern.
int a = 123;
int b = 100/10;
int c = 100%10;

printf("%d, %d, %d", a, b, c);

Ergibt für die Divisionen und Modulo-operationen genau einen Aufruf 
einer Divisionsfunktion.

Autor: Michael K. (mmike)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Simon: Dein Code würde folgendes ausgeben:
123, 10, 0
Was genau möchtest Du damit zeigen ?

Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Michael K. (mmike)

>@Simon: Dein Code würde folgendes ausgeben:
>123, 10, 0
>Was genau möchtest Du damit zeigen ?

Dass der Compiler (GCC?) so schlau ist zu erkennen, dass nur einmal mit 
Rest dividiert werden muss und somit die Divisionsroutine nur einmal 
aufruft.

MFG
Falk


Autor: Michael K. (mmike)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
coole Sache! Danke für Erklärung!

Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aus aktuellem Anlass.

Festkommaarithmetik

MFG
Falk

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.