mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik sprintf(" %2.4f" , value) erzeugt ein statt Zahlenwert


Autor: Timo P. (latissimo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute!

Grundlage ist stdio.h von winavr

Code:
value = (temp << 12) / 65535;     // temp ist unsigned int
sprintf(s, "float: %2.4f \r\n", value);

Die Ausgabe ist folgende:

float: ?

Hat jemand eine Idee?
(s ist folgendermaßen deklariert: uchar s[30]; und ist damit groß genug 
für mein Vorhaben

Danke für Hilfe!

Autor: Benjamin S. (recycler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bei nem MSP430 ist es mir aufgefallen, dass die libc keine Floatzahlen 
formatiern kann. Das wird hier auch so sein.
Ich denke, das wurde nicht implementiert, weil es zu viel Speicher bei 
manchen Modellen verbraucht und es da zu Engpässen kommt.

Kann das jemand bestätigen bzw. dementieren?

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Forumsuche nach "printf fragezeichen" sollte euch weiterhelfen.

Autor: Carlos (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Timo,
Dein Format passt nicht:
%2.4:  die erste Zahl gibt die Gesamtstellen-Anzahl der Zahl an, incl. 
des Dezimalpunktes und die zweite Zahl gibt die Anzahl der 
Nachkommastellen an.
Du willst also eine Zahl mit 4 Nachkommastellen und Gesamtläng von nur 2 
Stellen ausgeben.
Da kann der Compiler nicht.
Dreh die Zahlen um:  %4.2   ergibt: zwei Nachkommastellen, einen 
Dezimalpunkt und eine Vorkomma-Stelle, insgesamt also 4 Stellen.

Viele Grüße

Carlos

Autor: Timo P. (latissimo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
%6.4f wird nicht helfen! ich habe schon ganz neutral %f ausprobiert.

wenn temp zb. d376 ist dann kommt für value 23,5 raus. müsste doch mit 
%2.2f darstellbar sein....

wie gesagt, selbst %f ohne große formatierungsflags erzeugt mir ein ?

Autor: Timo P. (latissimo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
im übrigen gehts um den atmega 32,
astudio mit winavr

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Carlos (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Timo,
%2.2 wird auch nicht funktionieren, da der Dezimalpunkt immer als Stelle 
mit zählt !

Carlos

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Problem liegt hier daran, daß ein nicht-float-fähiges printf 
verwendet wird.


Selbst wenn %1.3f als Formatstring verwendet wird, gibt printf etwas 
sinnvolles aus.

Das hier vorliegende Problem aber liegt daran, daß die verwendete 
Library eben aus Gründen der Codegröße gar keine Unterstützung für die 
Float-Ausgabe via printf enthält.

Autor: Arc Net (arc)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Timo P. schrieb:
> Hallo Leute!
>
> Grundlage ist stdio.h von winavr
>
> Code:
>
> value = (temp << 12) / 65535;     // temp ist unsigned int
> sprintf(s, "float: %2.4f \r\n", value);
> 

In dieser Form wird nie etwas richtiges rauskommen.
Selbst wenn value ein Float ist, wird die Rechnung (temp << 12) / 65535 
trotzdem auf Integern ausgeführt und erst danach in einen Float 
umgewandelt. D.h. entweder passend in Float casten oder mit 
Fixpunkt-Rechnen und selber umwandeln, wenn printf mit 
Float-Unterstützung zu viel Speicher braucht.

> d376 ist dann kommt für value 23,5
0xd376 * 4096 / 65535 = 3383

> Dreh die Zahlen um:  %4.2   ergibt: zwei Nachkommastellen, einen
> Dezimalpunkt und eine Vorkomma-Stelle, insgesamt also 4 Stellen.

%[flags][width][.precision] [{h | l | ...}]type
width gibt an welche Mindestanzahl von Stellen ausgegeben wird, hat die 
Zahl mehr Stellen werden diese immer ausgegeben (falls weniger wird je 
nach Flags entsprechend aufgefüllt)

Autor: Timo P. (latissimo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
jetzt schon ;)

im übrigen geht 3.1 für z.B. 23.5 Grad ganz gut.
(ja hier ist es so warm....)
werd mal die türe vom serverraum aufmachen für kühle luft im büro...

Besten Dank an "sternst"

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

Bewertung
0 lesenswert
nicht lesenswert
Timo P. schrieb:
> jetzt schon ;)
>
> im übrigen geht 3.1 für z.B. 23.5 Grad ganz gut.

Dann frage ich mich, wozu du die Gesamtgröße des Ausgebfeldes überhaupt 
angibst, wenn du es sowieso zu klein angibst und nichts dabei findest.

23.5   besteht nunmal aus 4 Stellen ( '2' '3' '.' '5' )

Autor: schüchterner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
was soll denn 0xd376 sein?
habe extra d geschrieben, um zu sagen, dass es sich um den dezimalwert 
handelt

und du machst daraus einfach mal aus d... einen 0x... wert

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Statt des zu kurzen %3.1f (das nur positive Werte mit einer 
Vorkommastelle zulässt) genügt hier auch ein %.1f. Das bedeutet: 
"Feldbreite so breit wie nötig, aber genau eine Nachkommastelle".

Wenn man tabellarisch mehrere Werte ausgeben möchte, ist es aber 
sinnvoll, sich über die Feldbreite Gedanken zu machen.

Angenommen, wir haben folgende Werte: 1.34, 12.20, 263.48, 1234.56 und 
-7827.21 und wollen diese immer mit zwei Nachkommastellen ausgeben.

Diese durch "%.2f" geschickt ergeben folgendes Bild:

   "1.34"
   "12.20"
   "263.48"
   "1234.56"
   "-7827.21"

Das sieht als Tabelle richtig schlecht aus. Damit das vernünftig 
aussieht, müssen die Werte rechtsbündig ausgegeben werden, so daß der 
Dezimalpunkt immer an der selben Stelle steht.

Um das zu erreichen, muss eine unterschiedliche Anzahl von führenden 
Leerzeichen ausgeben werden.

Nun könnte man die Stringlänge bestimmen und von Hand Leerzeichen davor 
ausgeben, aber das ist gar nicht nötig - hier kommt die 
Feldbreitenangabe von printf hilfreich ins Spiel. Ist nämlich die 
angegebene Feldbreite größer als die tatsächlich benötigte, so stellt 
printf führende Leerzeichen voran.

Bestimmen wir jetzt mal die benötigte Feldbreite.

Der "größte" Wert hat vier Vorkommastellen, also muss das Format darauf 
angepasst werden. Hinzu kommen zwei Nachkommastellen, ein Dezimalpunkt 
und das Vorzeichen, in Summe also 8 Zeichen.

Also lautet der Formatstring "%8.2f". Angewand auf obige Zahlen ergibt 
sich dann folgendes Bild:

   "¬¬¬¬1.34"
   "¬¬¬12.20"
   "¬¬263.48"
   "¬1234.56"
   "-7827.21"

(Leerzeichen sind der Klarheit halber durch ¬ ersetzt)

Bei der Ausgabe hexadezimaler Zahlen ist die Ausgabe führender Nullen 
üblich, um klar erkennen zu lassen, welche Bitbreite die jeweilige Zahl 
hat.

Um die Zahlen 0x12, 0xF, 0xD12 und 0xFEED als 16-Bit-Werte auszugeben, 
ist eine Feldbreite von vier erforderlich (printf setzt kein 0x-Präfix, 
das muss man selber machen).


"%4X" ergibt

   "¬¬12"
   "¬¬¬F"
   "¬D12"
   "FEED"

Um anstelle des führenden Leerzeichens Nullen auszugeben, muss 
zusätzlich zur Feldbreite eine "0" vorangestellt werden:

"%04X" ergibt

   "0012"
   "000F"
   "0D12"
   "FEED"


Es ist also meistens sehr sinnvoll, sich mit den Formatspezifizierern 
und Feldbreitenangaben von printf im Detail zu beschäftigen.

Autor: Arc Net (arc)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rufus t. Firefly schrieb:
> Statt des zu kurzen %3.1f (das nur positive Werte mit einer
> Vorkommastelle zulässt)

Kleine Korrektur: Das  ergibt immer genau eine Nachkommastelle und n 
Vorkommastellen (wenn es so viele gibt).

7.19.6.1 (Ansi C99)
> — An optional minimum field width. If the converted value has fewer
> characters than the field width, it is padded with spaces (by default)
> on the left (or right, if the left adjustment flag, described later, has
> been given) to the field width. The field width takes the form of an
> asterisk * (described later) or a nonnegative decimal integer.235)
>
> — An optional precision that gives the minimum number of digits to
> appear for the d, i, o, u, x, and X conversions, the number of digits to
> appear after the decimal-point character for a, A, e, E, f, and F
> conversions, the maximum number of significant digits for the g and G
> conversions, or the maximum number of bytes to be written for s
> conversions. The precision takes the form of a period (.) followed
> either by an asterisk * (described later) or by an optional decimal
> integer; if only the period is specified, the precision is taken as
> zero. If a precision appears with any other conversion specifier, the
> behavior is undefined.

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Missverständnis:

> > Statt des zu kurzen %3.1f (das nur positive Werte mit einer
> > Vorkommastelle zulässt)
>
> Kleine Korrektur: Das  ergibt immer genau eine Nachkommastelle und n
> Vorkommastellen (wenn es so viele gibt).

Das war so gemeint, daß in die Feldbreite 3 eben nur positive Werte mit 
einer Vorkommastelle hineinpassen - für alles andere wird die 
Feldbreite entsprechend automatisch erweitert, was Du ja auch sehr 
schön beschreibst.

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.