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
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
Probier mal: float temperature = (char)(MeasValues.Temperature >> 8); // Vor dem Komma temperature += (float)(((char)MeasValues.Temperature) / 100.0f); // Nach dem Komma .... Grüße Michael
sorry, nicht richtig gelesen... einfach tamp mit MeasValues.Temperature ersetzen...
vertippt .... temperature += (float)((char)MeasValues.Temperature) / 100.0f;
So vielleicht:
1 | float Get_Temp(int16_t tempIn) |
2 | {
|
3 | float temperature; |
4 | |
5 | temperature = (float)(tempIn>>8); // vorkomma |
6 | tempIn &= 0xff; // HighByte zu Null setzen |
7 | temperature += (float)(tempIn)/256.0; //Nachkomma |
8 | |
9 | return temperature; |
10 | }
|
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?
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.
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
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.
> 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.
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.
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...
@ Johannes. Wie soll das mit der Berechnung und der Speicherung als String funktionieren?
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!
Probier mal: sprintf(Buffer,"%d,%d °C", (char)(MeasValues.Temperature >> 8), (char)(MeasValues.Temperature & 0xFF)); Was wird dann angezeigt ?
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?
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.
QJohannes. danke für den Tip. Probier ich morgen aus. Hab jetzt leider keine Zeit mehr. Trotzdem danke. Stefan
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.
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.
1 | int a = 123; |
2 | int b = 100/10; |
3 | int c = 100%10; |
4 | |
5 | printf("%d, %d, %d", a, b, c); |
Ergibt für die Divisionen und Modulo-operationen genau einen Aufruf einer Divisionsfunktion.
@Simon: Dein Code würde folgendes ausgeben: 123, 10, 0 Was genau möchtest Du damit zeigen ?
@ 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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.