C >>> falscher Datentyp?

OP #5333265
Lesenswert?

Hallo.
Mir scheint, dass Variable der folgenden Formeln im Prog-Auszug nicht 
richtig definiert wurden.
Prog. reagiert nicht auf Änderungen Poty01, Poty02

Sollte Periode und PosWelleProzent als uint64_t definiert werden?
Wert von Var. PosWelle und NegWelle müssen nach Berechnung Ganzzahlig 
zw. 1-1000 liegen.
_______________________________________________
main...  // Nachfolgendes funktioniert nicht

uint16_t Poty01;   // aus ADC ausgelesen, 0-1023
uint16_t Poty01_alt = 0; // 0-1023
uint16_t Poty02;   // aus ADC ausgelesen, 0-1023
uint16_t Poty02_alt = 0; // 0-1023
uint16_t Periode;
uint16_t PosWelleProzent;
uint16_t PosWelle;
uint16_t NegWelle;
uint8_t Veraenderung = 0;
...
//werden unter Präprozessor-Makro definiert
FREQ_BEREICH=999;
FREQ_LOW=1;
PWM_BEREICH=90;
PWM_LOW=5;
...
Veraenderung=1;
switch(Veraenderung)
{
case 1:
Periode = FREQ_BEREICH/1024*Poty01+FREQ_LOW;
                      //nach case=1 direkt case=2 abarbeiten
case 2:
PosWelleProzent = PWM_BEREICH/1024*Poty02+PWM_LOW;
PosWelle = Periode/100*PosWelleProzent;
NegWelle = Periode-PosWelle;
break;
}
...
#5333296
Lesenswert?

Hallo,

Periode = FREQ_BEREICH/1024*Poty01+FREQ_LOW;

was kommt da raus? C rechnet in Integer wenn nicht zwingend anders 
angegeben.
999/1024 = 0
0*Poty01 = 0
ü+FREQ_LOW = 1

kommt also immer 1 raus, bei der 2. Formel eben 5.

FREQ_BEREICH*Poty01/1024+FREQ_LOW könnte da eher gehen.
Da passt die Rechnung aber dann nicht in 16 Bit, also mindestens einen 
der Werte der Formael auf 32 Bit casten.

Gruß aus Berlin
Michael
OP #5333344
Lesenswert?

Michael U. schrieb:
> 999/1024 = 0
Klar, rutscht unter 0
Dürfte bei uint64_t egal sein - oder?

Michael U. schrieb:
> FREQ_BEREICH*Poty01/1024+FREQ_LOW könnte da eher gehen.
Gleiche Formel, aber auch Dezimalstellen.


PS:
Wie ist das bei uint16_t, wird erste Dezimalstelle auf/abgerundet. 
Ganzzahlig bleibt unberührt erhalten?
Bsp:
uint16_t PosWelle=9,71234;
Steht in PosWelle jetzt 9, oder 10 ?
OP #5334215
Lesenswert?

Michael U. schrieb:
> __Son´s B. schrieb:
>> Klar, rutscht unter 0
>> Dürfte bei uint64_t egal sein - oder?
>
> auch ein 64Bit unsigned Integer ist ein Ganzzahlwert und es kommt 0
> raus.

Stimmt - habe unter C99-Standard keine Fließkomma-Definition gefunden.
Gibts das überhaupt?
_________________________________

Kaj G. schrieb:
>> Steht in PosWelle jetzt 9, oder 10 ?
> 9. Es wird einfach nur der Nachkommaanteil abgeschnitten.
Kirsch schrieb:
>> int16_t PosWelle=9,71234;
>> Steht in PosWelle jetzt 9, oder 10 ?
>
> es wird immer abgerundet
Rolf M. schrieb:
>>> Steht in PosWelle jetzt 9, oder 10 ?
>>
>> es wird immer abgerundet
>
> Nein, es wird der Nachkommateil abgeschnitten. Das heißt, dass im Falle
> eines negativen Wertes aufgerudet wird.

Ok, damit kann man kalkulieren.
___________________________________

Markus F. schrieb:
>> uint16_t PosWelle=9,71234;
>> Steht in PosWelle jetzt 9, oder 10 ?
>
> weder noch. Das gibt einen Fehler beim Compilieren.

Mein Compiler (Atmel Studio 7.0) wirft keine Fehler raus.
___________________________________

Daniel A. schrieb:
>> uint16_t PosWelle=9,71234;
>> Steht in PosWelle jetzt 9, oder 10 ?
>
> Wenn du um 9,71234 noch eine runde Klammer machst kommt 71234 raus.
Kaj G. schrieb:
>> Wenn du um 9,71234 noch eine runde Klammer machst kommt 71234 raus.
> Es waere 5698 ;)

Was stimmt denn nun?
Welche Logik steckt dahinter.
Gast #5334254
Lesenswert?

>> uint16_t PosWelle=9,71234;

__Son´s B. schrieb:
>>> Wenn du um 9,71234 noch eine runde Klammer machst kommt 71234 raus.
>> Es waere 5698 ;)
>
> Was stimmt denn nun?
> Welche Logik steckt dahinter.

Ohne Klammer würde eine weitere variable vom Typ uint16_t angelegt 
werden
wollen. Da würde aber der Name fehlen -> Error.

Mit Klammer ist es ein ganz normales Komma als Operator. Das Ergebnis 
des
Ausdrucks ist dann das, was rechts vom Komma steht, also 71234.
OP #5334362
Lesenswert?

DANKE!

Noch eine wichtige Frage zu Berechnungen;
-------------------------
uint16_t Poty01; // Wert aus ADC kann zw.0-1023 liegen
if (Poty01<1) Poty01=1; // Berechnungssicherheit

uint16_t periode=999/1024*Poty01+5;
// oder //
uint16_t periode=999*Poty01/1024+5;
-------------------------
Frage 1:
Unterscheidet der Compiler zwischen beiden Varianten?
Frage 2:
Werden INNERHALB der Berechnungen, Dezimalstellen ordentlich mit 
Nachkomma berechnet und erst dem Ergebnis die Dezimalstellen 
abgeschnitten?
#5334438
Lesenswert?

Der Compiler wertet den Ausdruck im mathematischem Sinn aus.
Also Klammer- vor Punkt- vor Strichrechnung.

Und der Datentyp ist der, der für die Berechnung des aktuellen 
Teilausdrucks ausreichend ist.

Fall 1:
uint16_t periode=999/1024*Poty01+5;

999/1024 ist eine Integerdivision. Keine implizite Umwandlung in float. 
Da kommt 0 raus

*Poty01 Integermultiplikation, da das vorhergehende Ergebniss auch 
Integer war und das Ergebnis negativ sein könnte (egal dass da nur 
positive Werte sind)
+ 5  Addition (geschenkt)


Fall 2

uint16_t periode=999*Poty01/1024+5;

999*Poty01 Ob das Probleme macht, hängt davon ab, wir groß ein int bei 
dir ist. Bei 16-Bit gibt es Probleme (überlauf), bei 32-Bit nicht.

Da du jetzt eine große Zahl hast, gibt es beim
/1024 kein Problem mehr.

Da es bei diesen Fällen zu unterschiedliche Ergebnisse kommt (was 
durchaus gewünscht sein kann), muss der Compiler die Fälle 
unterscheiden.


Wenn du im zweiten Fall 999L statt 999 schreibst, sollte das Problem 
behoben sein.
OP #5334496
Lesenswert?

Rufus Τ. F. schrieb:
> __Son´s B. schrieb:
>> Werden INNERHALB der Berechnungen, Dezimalstellen ordentlich mit
>> Nachkomma berechnet
>
> Nein, wenn Du nur Ganzzahlen angibst, wird auch nur mit Ganzzahlen
> gerechnet.
>
> Lies ein C-Buch.
>
> Das haben wir Dir in den vergangenen Jahren wohl schon das eine oder
> andere Mal nahegelegt, wenn ich mich recht erinnere.

Tja, offensichtlich habe ich eher oberflächliche C-Fachbücher. Dort wird 
nur so dividiert, dass Ganzzahlen raus kommen - Einsteiger-Niveau.
Grundsätzlich finde ich den Verweis auf Datenblätter und Literatur 
sinnvoll, NACH einer ordentlichen, dem Einsteiger angepassten 
Beschreibung - zur Wissensvertiefung!

Gott sei dank, gibt es hier im Forum aber auch Menschen mit kostruktiven 
Anregungen.
Denen, meinen tiefen Dank!
Persönliche Seite #5334512
Lesenswert?

__Son´s B. schrieb:
> Tja, offensichtlich habe ich eher oberflächliche C-Fachbücher. Dort wird
> nur so dividiert, dass Ganzzahlen raus kommen - Einsteiger-Niveau.
> Grundsätzlich finde ich den Verweis auf Datenblätter und Literatur
> sinnvoll, NACH einer ordentlichen, dem Einsteiger angepassten
> Beschreibung - zur Wissensvertiefung!

Nö, die Ausrede lasse ich nicht gelten.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren