2016-11-11 1 views
-3

Sehr geradlinig. Der folgende Code ist von einem meiner Funktionen:Fließkommaausnahme?

int i, j; 
for (i = 0; i < m; i++) { 
    for (j = 0; j < numberOfVariables; j++) { 
     if ((j % i) == 0 && i != 0) { 
      table[i][j] = 1; 
     } 
    } 
} 

Als ich es nennen, erhalte ich eine Gleitkomma-Ausnahme. Außer dass ich mit keinen Gleitkommazahlen arbeite. Was passiert genau?

+2

Sie erhalten es, weil Sie durch Null teilen. 'if ((j% i) == 0 ', wenn' j = 0 'und' i = 0 '. –

+2

Es ist nicht unüblich, dass einige Plattformen Gleitkommaausnahmen als Reaktion auf arithmetischen Überlauf oder Division durch Null ausgeben, selbst wenn keine Gleitkommatypen in Berechnungen involviert sind. – AnT

Antwort

8

Wenn i Null ist, enthält j % i Division durch Null, was nicht erlaubt ist.

es zu vermeiden, müssen Sie dies ändern:

 if ((j % i) == 0 && i != 0) { 

dazu:

 if (i != 0 && (j % i) == 0) { 

(unter Ausnutzung der Kurzschließen Verhalten von &&: wenn die linken Operand wird zu false ausgewertet, dann wird der rechte Operand nie ausgewertet).

+3

... oder starten Sie die Schleife über "i" von "1" und eliminieren Sie den "i! = 0" -Test – Leon

0

Wenn Sie in Ihrer Schleife (j % i) == 0 für i=0 auswerten, wird dies durch 0 im Hintergrund geteilt. Daher die Gleitkommaausnahme.

int i,j; 
    for (i = 0; i < m; i++) { 
    for (j = 0; j < numberOfVariables; j++) { 
     if (i != 0 && (j % i) == 0) { 
     table[i][j] = 1; 
     } 
    } 
    } 

Zur Laufzeit wird es bewerten, dass i==0 und die Modulo Auswertung überspringen. Die Art und Weise, wie Sie zuvor gearbeitet haben, bestand darin, das Modulo zu überprüfen, bevor Sie das i!=0 bestätigen.

1

Betrachten wir die erste Iteration:

if ((j % i) == 0 && i != 0) { 

&& und || den linken Operanden immer zuerst bewerten, und die Bedingung Kurzschluss wird, wenn die Bedingung dreht falsch. Diese

bedeutet, dass, wenn i != 0, es wird j % iersten, bewerten und so Division durch Null. Beachten Sie, dass Division durch Null ein undefiniertes Verhalten ist.

Sie müssen diese Zeilen ersetzen durch:

if (i != 0 && (j % i) == 0) { 

diese Weise, wenn i == 0, (j % i) == 0 nicht

ausgewertet werden, sondern diese Prüfung zu tun, können Sie nicht nur direkt, diesen Fall vermeiden ? Sie können einfach i1-m statt laufen, so dass Sie auch das Kontroll entfernen:

for (i = 1; i < m; i++) { 

Edit: Ihre Laufzeit beanspruchen Sie eine Gleitkomma-Ausnahme aufgetreten wahrscheinlich falsch und verwechselte eine arithmetische Ausnahme als Division durch Null; oder es könnte aufgrund einer Compiler-Optimierung sein. Etwas in dieser Richtung.