Forum: Mikrocontroller und Digitale Elektronik Division by Zero


von Christian S. (mueke)


Lesenswert?

Hallo Leute,
ich habe in mein Quelltext folgende Berechnung für mein ATMEGA16 
eingeügt und bekomme Warnungen: Division by Zero

Ich weiß aber nicht warum, ich dividiere doch gar nicht durch 0...


MFG
Muecke

von Christian S. (mueke)


Lesenswert?

Sorry, ei wenig durcheinander. Hier natürlich noch der Quelltext:
1
if(CONFIG.FREQ <= 100 && CONFIG.FREQ != 0)
2
        OCR1A = ((1/CONFIG.FREQ) / (1/(4000000/64))) / 2;
3
4
else if(CONFIG.FREQ > 100 && CONFIG.FREQ <= 255)
5
  OCR1A = ((1/CONFIG.FREQ) / (1/(4000000/8))) / 2;
6
7
else if(CONFIG.FREQ < 255)
8
  OCR1A = ((1/CONFIG.FREQ) / (1/4000000)) / 2;

von Willi W. (williwacker)


Lesenswert?

Quelltext ?

von T.Stütz (Gast)


Lesenswert?

(1/(4000000/8)) = 0 da nicht als float/double gerechnet !

Gruß

von Timo (Gast)


Lesenswert?

Ich glaube schon:

1/(4000000/64)

müsste eigentlich eine Integeroperation sein, da kommt also Null raus.
Probier es mal mit:

((1.0/CONFIG.FREQ) / (1.0/(4000000.0/64.0))) / 2.0

CONFIG.FREQ muss ein Float sein.

von Johannes S. (johanness)


Lesenswert?

Ich hab jetzt mal keine Ahnung, was CONFIG.FREQ ist, vermute aber eine 
Gleitkommavariable dahinter.

Fehler liegt z.B. hier:

1/(4000000/64)

Du dividierst 1 durch einen ziemlich großen Wert. Beides sind 
Ganzzahlen, das Ergebnis ist eine Ganzzahl und wird abgerundet, also auf 
0. Warum invertierst du die Zahl, um dann dadurch zu dividieren? Lass 
das 1/ und mach aus dem / davor ein *.

von Willi W. (williwacker)


Lesenswert?

Die letzte Zeile kann erreicht werden wenn CONFIG.FREQ==0 und dann hast 
Du eine Division by Zero

von Christian S. (mueke)


Lesenswert?

OK Danke. ich habe überall ein ".0" angefügt und CONFIG.FREQ gecastet... 
Funktioniert nun

von Timo (Gast)


Lesenswert?

Der Sinn der letzten else if Anweisung erschliesst sich mir aber auch 
nicht. Wofür soll die sein?

von Johannes S. (johanness)


Lesenswert?

Anmerkung nebenbei...

Wäre es für deine Anwendung ungünstig, die Formel

((1/CONFIG.FREQ) / (1/(4000000/64))) / 2;

umzustellen als

(4000000/64)  2  CONFIG.FREQ;

? Ich denke das ist eher das, was du meinst, und die Konstanten am 
Anfang kann ein vernünftiger Compiler auch besser zusammenfassen.

Beschreibe doch mal, was CONFIG.FREQ ist (Ganzzahl, Fließkommazahl, in 
welchem Wertebereich).

von Joerg X. (Gast)


Lesenswert?

Es müsste doch reichen, die 4Mio. als "long" zu kennzeichnen ("L" 
anhängen), oder? (besser als zu 'riskieren', dass die Float-Berechnung 
nicht wegoptimiert wird)
hth. Jörg

von Christian S. (mueke)


Lesenswert?

CONFIG.FREQ ist definiert als uint16_t.
Also eine 16bit-Zahl. Hiermit sollen die Frequenzen erzeugt werden mit 
Timer1 und es funktioniert jetzt soweit. Mit dem Umstellen werde ich mal 
probieren... Danke...

von Johannes S. (johanness)


Lesenswert?

Immer an Mathe denken: A/(1/B)==A*B
Das erste geht hier durch die Integerarithmetik schief, also warum die 
linke Seite verwenden, wenn die rechte besser geht? Denn die 
Spezialitäten der Integerarithmetik willst du ja eigentlich gar nicht.

Und die if-Abfragen würde ich noch einmal überarbeiten. Besonders das < 
in der letzten Abfrage sollte ein > sein.

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.