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


von Timo P. (latissimo)


Lesenswert?

Hallo Leute!

Grundlage ist stdio.h von winavr

Code:
1
value = (temp << 12) / 65535;     // temp ist unsigned int
2
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!

von Benjamin S. (recycler)


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?

von Gast (Gast)


Lesenswert?

Forumsuche nach "printf fragezeichen" sollte euch weiterhelfen.

von Carlos (Gast)


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

von Timo P. (latissimo)


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 ?

von Timo P. (latissimo)


Lesenswert?

im übrigen gehts um den atmega 32,
astudio mit winavr

von Stefan E. (sternst)


Lesenswert?


von Carlos (Gast)


Lesenswert?

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

Carlos

von Rufus Τ. F. (rufus) Benutzerseite


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.

von Arc N. (arc)


Lesenswert?

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

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)

von Timo P. (latissimo)


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"

von Karl H. (kbuchegg)


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' )

von schüchterner (Gast)


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

von Rufus Τ. F. (rufus) Benutzerseite


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.

von Arc N. (arc)


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.

von Rufus Τ. F. (rufus) Benutzerseite


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.

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.