Hallo, ich habe zwei Zahlen:
1 | |
Wie kann ich diese Zwei in eine machen die dann so aussieht: z1,z2, also dass z1 vorkommastellen sind und z2 Nachkommastellen?
|
Anzeige
|
C - Zwei Zahlen zu einer MappenHallo, ich habe zwei Zahlen:
Wie kann ich diese Zwei in eine machen die dann so aussieht: z1,z2, also dass z1 vorkommastellen sind und z2 Nachkommastellen? Martin Fischer schrieb: > Wie kann ich diese Zwei in eine machen die dann so aussieht: > z1,z2, also dass z1 vorkommastellen sind und z2 Nachkommastellen? Wie sieht das Format dieser "Nachkommastellen" denn aus? Wenn z.B. die "Nachkommastellen" im Bereich von 0..9999 wären, dann würde das so gehen:
> Wie kann ich diese Zwei in eine machen die dann so aussieht:
Was ich gerne wissen würde: wofür brauchst du diese Zahl?
Gast
#3546297
Festkommaarithmetik Danke, berecnet habe ich geschafft, aber auf einem anderen Weg, ich demonstriere kurz was ich brauche: Temperaturmessung: uint8_t digit = 32; uint16_t decimal = 4493; -> Temperatur ist 32.4493 °C Ich mag das jetzt in eine Zahl packen: uint32_t temp = (digit *10000 + decimal)/10000 Und das dann auf dem Display ausgeben -> erst zu nem char array machen: char buffer[20]; sprintf(buffer, "%d C", temp); -> Fehler: temp != decimal... Wie mache ich das? Und ist uint32_t überhaupt richtig um die zu "addieren"? Wenn du nach deiner Aktion eine Kommazahl haben möchtest, dann solltest du keinen int-Datentyp wählen !
diese Zeile macht nicht viel Sinn :)
Gast
#3546317
Wenns am Ende sowieso ein String sein soll, kann man den doch aus den int's basteln, oder liege ich da falsch?
Gast
#3546318
Überleg mal was mit den decimals passiert, wenn du sie durch 10000 teilst. Wo stehen die dann in temp? Wenns nur um die Ausgabe geht:
Nebenbei: Temperatur mit 6 signifikanten Stellen?
Gast
#3546320
Verdammt! Zu lange getippt! ;-) Martin Fischer schrieb: > Ich mag das jetzt in eine Zahl packen: > uint32_t temp = (digit *10000 + decimal)/10000 Wozu dann durch zehntausend teilen? Ein Integer kann keine Nachkommastellen speichern. Warum speicherst du nicht einfach milliGrad in einem Integer? > Ich mag das jetzt in eine Zahl packen: > Und das dann auf dem Display ausgeben - Warum erst zusammenpacken und dann wieder auseinanderdröseln? Gib doch erst die Vorkommastellen aus, dann ein Komma, dann die Nachkommastellen. Das ist das Einfachste... > Temperaturmessung: > uint8_t digit = 32; > uint16_t decimal = 4493; > -> Temperatur ist 32.4493 °C Ähm, wenn GENAU das deine Anwendung ist, dann bezweifle ich sehr, dass du überhaupt so genau Messen kannst... Ich habe diese Funktion:
Und mag hiermit das auf dem Display ausgeben:
Auf dem Display steht aber nur "0.0000 C", warum? Martin Fischer schrieb: > Auf dem Display steht aber nur "0.0000 C", warum? Weil in grad und grad_dec jeweils Null ist? > therm_read_temperature(grad, grad_dec); Diese Funktion KANN die Werte von grad und grad_dec nicht ändern. Du solltest dir dringend anschauen, wie Funktionen mehrere Werte bearbeiten können. Mein Tipp: man verwendet dafür dann Pointer... Probiers also einfach mal so:
> Warum erst zusammenpacken und dann wieder auseinanderdröseln? Gib doch > erst die Vorkommastellen aus, dann ein Komma, dann die Nachkommastellen. > Das ist das Einfachste... Aber ich brauche die Zahl dann noch zum weiteren Rechnen, also wie kann ich meine Temperatur zusätzlich noch in eine zahl packen um damit zu rechnen? Martin Fischer schrieb: > Aber ich brauche die Zahl dann noch zum weiteren Rechnen, also wie kann > ich meine Temperatur zusätzlich noch in eine zahl packen um damit zu > rechnen? Wenn du unbedingt mit Integern weiterrechnen willst, dann rechne in milliGrad (aka. Festpunktartihmetik). Am einfachsten ist aber, du verwendest float... > float
Ich brauche aber die 4 Nachkommastellen..
Gast
#3546346
Martin Fischer schrieb: > uint32_t temp = (digit *10000 + decimal)/10000 digit * 10000 <=> 32 * 10000 = 320000 + decimal <=> + 4493 = 324493 / 10000 <=> / 10000 = 32 Dein Problem ist das du nur mit Ganzzahlen(Integer) arbeitest, wenn du aber 324493 / 10000 erhältst du allerdings eine Zahl mit Nachkommastellen(Fließkommazahl). Weil temp und ALLE anderen Variablen vom Typ Integer sind werden die Nachkommastellen abgeschnitten. Bei entsprechender Compiler-Optimierung wird die komplette Rechnung wahrscheinlich sogar entfernt werden. Die Frage ist nun ob du mit der kompletten Zahl noch rechnen möchtest oder ob du sie nur zur Darstellung/Ausgabe benötigst. Musst du noch damit rechnen, kannst du a) Festkommaarithmetik verwenden, dann müssen alle weiteren Operanden noch mit 10000 multipliziert werden. Erst am Ende wenn es zur Darstellung kommt wandelst du die Zahl in eine Fließkommazahl. b) Du rechnest komplett mit Fließkommazahlen so wie Lothar es dir weiter oben gezeigt hat. Wenn du die Zahl nur noch darstellen möchtest und sie unbedingt in einer Variablen speichern möchtest kann die Zahl auch anders zusammen gepackt werden. uint32 temp = (digit << 16) + decimal; char buffer[20]; sprintf(buffer, "%d.%d C", temp >> 16, temp & 0xFF);
Gast
#3546349
Martin Fischer schrieb: >> float > > Ich brauche aber die 4 Nachkommastellen.. Was für ein Monster-Thermometer hast du denn da, daß du dafür eine Auflösung von 1/10000 Kelvin brauchst, und wieviele Millionen kostet sowas? Martin Fischer schrieb: >> float > > Ich brauche aber die 4 Nachkommastellen.. Bei Temperatur? Welcher Messbereich schwebt dir denn vor?
Gast
#3546353
Wenn du Temperaturen auf 6 signifikante Stellen messen kannst, dann hast du auch noch Geld übrig, eine C-Programmierer zu bezahlen, der dir deine SopW-Probleme löst. (warum glaubt man heute eigentlich blind an jede Zahl, die per 7-Segment angezeigt wird?) Es ist ein DS18B20 auf 12bit Auflösung...
Gast
#3546366
Und +-0.5C Genauigkeit! Martin Fischer schrieb: > Es ist ein DS18B20 auf 12bit Auflösung... LOL Aus dem Datenblatt: It has an operating temperature range of -55°C to +125°C and is accurate to ±0.5°C over the range of -10°C to +85°C. In Also reicht eine Nachkommastelle. Jaja. Ich habe jetzt aber noch ein Problem:
Beim Compilieren: main.c:28:9: warning: format ‘%f’ expects argument of type ‘double’, but argument 3 has type ‘float’ [-Wformat]
Gast
#3546384
Statt temp einfach (double)temp übergeben. Martin Fischer schrieb: > Jaja. heißt ""Klei mi ann Mors" Bei Funktionen mit variabler Argumentenliste wird float immer auf double erweitert. Error: prop -fno-inline-small-functions -I. -mmcu=atmega328p -DF_CPU=8000000 main.c: In function ‘main’: main.c:27:23: error: expected expression before ‘double’ make: *** [main.o] Fehler 1 Was bedeutet das denn jetzt? Ich habe alle floats einfach mit double ersetzt Anscheinend aber nicht richtig. Wie sollen wir das ohne Code beurteilen. Der Fehler ist aber vor der Spalte 23 in Zeile 27.
Gast
#3546399
>Ich habe alle floats einfach mit double ersetzt Ich vermute eher, das Du alle Strings "float" im Programmtext durch den String "double" ersetzt hast. >main.c:27:23: error: expected expression before ‘double’ Gut, das wir die Zeile 27 nicht sehen können. Da wird das raten viel spannender. Zeile 27: temp = grad + double(grad_dec)/10000.0; Und temp-definition: double temp;
Gast
#3546413
Da hat sich Lothar verhauen. Zuviel VHDL nehme ich a. :-)
Martin Fischer schrieb: > Zeile 27: > temp = grad + double(grad_dec)/10000.0; Da gehört ein Cast hin. Den schreibt man in (). Aber der ist auch gar nicht nötig, da 10000.0 schon ein double ist und somit die Division schon in double berechnet wird.
Gast
#3546421
Martin Fischer schrieb: > double(grad_dec) Das ist nicht C. Sowas geht in C++, aber nicht in C. In C sieht ein Cast so aus:
Martin Fischer schrieb: > main.c:28:9: warning: format ‘%f’ expects argument of type ‘double’, but > argument 3 has type ‘float’ [-Wformat] Das ist merkwürdig. Normwalerweise wird das implizit nach double konvertiert, ohne Warnung. Nanu???
temp = grad + ((double) grad_dec)/10000;
sprintf(buffertemp, "%f C", temp);
-> auf Display: "? C"
Gast
#3546433
Sieht aus, als wenn Du eine besondere Library benutzt. Poste mal alle Kommandozeilen. 1. Ohne konvertierung zu Double hatte es ja auch geklappt. 2. Was meinst du mit Kommandozeilen? avr-gcc main.c -c -o main.o -Wall -Os -fno-move-loop-invariants -fno-tree-scev-cprop -fno-inline-small-functions -I. -mmcu=atmega328p -DF_CPU=8000000 avr-gcc lib/lcd.c -c -o lcd.o -std=c99 -Wall -Os -fno-move-loop-invariants -fno-tree-scev-cprop -fno-inline-small-functions -I. -mmcu=atmega328p -DF_CPU=8000000 avr-gcc lib/simpleprog.c -c -o simpleprog.o -std=c99 -Wall -Os -fno-move-loop-invariants -fno-tree-scev-cprop -fno-inline-small-functions -I. -mmcu=atmega328p -DF_CPU=8000000 avr-gcc lib/ds18b20.c -c -o ds18b20.o -std=c99 -Wall -Os -fno-move-loop-invariants -fno-tree-scev-cprop -fno-inline-small-functions -I. -mmcu=atmega328p -DF_CPU=8000000 avr-gcc main.o lcd.o simpleprog.o ds18b20.o -o main.elf -Wall -Os -fno-move-loop-invariants -fno-tree-scev-cprop -fno-inline-small-functions -I. -mmcu=atmega328p -DF_CPU=8000000 -Wl,-Map,main.map -Wl,--relax,--gc-sections . text data bss dec hex filename 4778 46 0 4824 12d8 main.elf .
Gast
#3546447
Dein Problem ist, daß du die Doku der avr-libc nicht gelesen hast. Da floating-point sehr viel Flash braucht, unterstützt das per default gelinkte printf keine Gleitkommazahlen. Bitte durchdenke alles nochmal genau: Brauchst du wirklich Dezimalzahlen? Dein Thermometer hat eine Genauigkeit von 0.5°C. D.h., wie schon gesagt wurde, du brauchst nur eine Dezimalstelle. Alle weiteren haben keine Aussagekraft! Nun könntest du auch alles mit Integer rechnen, indem du das Ergebnis mit 10 multiplizierst um die eine benötigte Dezimalstelle weg zu bekommen. Das ist schneller und verbraucht weniger Speicher. Zur Ausgabe auf dem Display kannst du dann entweder die Zahl mit Division durch 10 in ein Double speichern und wie gehabt ein Double mit sprintf am LCD ausgeben. Das dauert aber sehr lange, da die Umwandlung eines Double in einen String sehr Rechenintensiv ist. Wieder besser ist, du machst das 'manuell'. D.h. du teilst die Zahl durch 10, speicherst das Ergebnis in ein Int. Die Zahl mit 10 multipliziert und von der Ausgangszahl subtrahiert gibt dir die Dezimalstelle. Beides sind Int, beide können per sprintf mit minimalen Rechenaufwand ausgegeben werden. (Falls ich bei obiger Rechnung einen Denkfehler habe, so korrigiert mich bitte) Bitflüsterer schrieb: > temp = grad + double(grad_dec)/10000.0; > Da hat sich Lothar verhauen. Zuviel VHDL nehme ich a. :-) Ach verd*%&/$§ Ich könnte aber auch behaupten, ich hätte das gemacht, dass Martin mal ein wenig mitdenkt und keiner könnte das Gegenteil beweisen... ;-) Frank M. schrieb: > Nun könntest du auch alles mit Integer rechnen, indem du das Ergebnis > mit 10 multiplizierst Ja, dann eben in ZehntelGrad statt in milliGrad... Martin Fischer schrieb: > Ich brauche aber die 4 Nachkommastellen... Bitte die nächste Scheibe der Salami: Wofür brauchst du die real nicht vorhandenen 4 Nachkommastellen. Nochmal zum Mitschreiben: wenn dein Sensor eh' nur eine halbe signifikante Nachkommastelle ausgibt, dann ist es absolut sinnlos, wenn du dir eine 5000 fach höhere Auflösung herrechnest. Die Genauigkeit bleibt trotzdem gleich schlecht. Ja gut, da hast du recht :D Aber ich bin ANfänger und weiß sowas noch nicht :P naja, ich "Spiele" einfach jetzt mit allen werten *10, ist leichter, schneller, besser :D Danke trotzdem an euch allen!
Gast
#3546473
Nichts für ungut aber: Martin Fischer schrieb: > Aber ich bin ANfänger und weiß sowas noch nicht :P Casten und Fehlermeldung lesen gehört sowas von zu den Grundlagen, deshalb lerne sie und komme mit ihnen zurecht oder hör auf. Du kannst nicht immer wegen jedem kleinen Scheiß das Forum zumüllen.
Gast
#3546586
Ganz so schlimm würde ich das nicht sehen. Nur, oft wenn (von Anfänger und Anderstgläubigen) auf C geschimpft wird, hat der Compiler alles wichtige angemerkt, nur hatte man vorgezogen es zu ignorieren. Also bitte lesen. Wenn's dann allzu verwirrend wirkt, hilf sicher jemand ;-)
Gast
#3546668
Frank M. schrieb: > ... > Wieder besser ist, du machst das 'manuell'. D.h. du teilst die Zahl > durch 10, speicherst das Ergebnis in ein Int. Die Zahl mit 10 > multipliziert und von der Ausgangszahl subtrahiert gibt dir die > Dezimalstelle. Beides sind Int, beide können per sprintf mit minimalen > Rechenaufwand ausgegeben werden. > So:
Gast
#3546679
@ Lothar Miller >Ich könnte aber auch behaupten, ich hätte das gemacht, dass Martin mal >ein wenig mitdenkt und keiner könnte das Gegenteil beweisen... ;-) Dazu nehme ich 'ne Knoblauchzehe. Wirst schon sehen. :-) @ Martin Was soll Dein letztes Posting sein? Eine Frage oder eine Feststellung? Nebenbei: Ist das nun C oder C++? Leg Dich mal fest. :-) Antwort schreibenBitte melde dich an, um einen Beitrag zu schreiben. |
Anzeige
|