2011-01-13 6 views
63

Ich schrieb diesen Code:Warum ist das Ergebnis von 1/3 == 0?

public static void main(String[] args) { 
    double g = 1/3; 
    System.out.printf("%.2f", g); 
} 

Das Ergebnis ist 0. Warum ist das, und wie kann ich dieses Problem lösen?

Antwort

88

die beiden Operanden (1 und 3) ganze Zahlen sind, also Integer-Arithmetik (Zweiteilung) verwendet wird. Die Deklaration der Ergebnisvariablen als double bewirkt lediglich eine implizite Konvertierung nach der Division.

Integer-Division natürlich gibt das wahre Ergebnis der Division in Richtung Null gerundet. Das Ergebnis von 0.333... wird somit hier auf 0 abgerundet. (Beachten Sie, dass der Prozessor keine Rundung durchführt, aber Sie können sich das so vorstellen.)

Beachten Sie auch, dass beide Operanden (Zahlen) als Floats angegeben sind; 3.0 und 1.0, oder auch nur die erste, dann Fließkomma-Arithmetik verwendet wird, geben Sie 0.333....

+19

+1 und es immer abgerundet. 'int i = .99999999' setzt int auf 0. Genauer gesagt, nimmt es den ganzzahligen Teil und verwirft den Rest. –

+24

Es wird "auf Null" abgerundet, was für Werte größer als Null "nach unten" ist. (+0.9 wird auf 0 gerundet, -0.9 wird ebenfalls auf 0 gerundet) –

+0

@Byron: Ja, genau. Ich glaube nicht, dass der Prozessor tatsächlich eine Rundung durchführt, da die Aufteilung sehr unterschiedlich ist, aber es ist praktisch, so zu denken. – Noldorin

7

warf es Explizit als double

double g = 1.0/3.0 

Dies geschieht, weil Java die ganzzahligen Teilungsoperation für 1 und 3 verwendet, da man sie als Integer-Konstanten eingegeben.

0

1 und 3 sind integer contants und so Java macht eine Integer-Division, die Ergebnis ist 0. Wenn Sie doppelte Konstanten schreiben möchten, müssen Sie schreiben 1.0 und 3.0.

-1

Do "double g = 1,0/3,0;" stattdessen.

+0

Nur neugierig ... was ist los mit dieser Antwort? Ich habe diesen Ansatz verwendet, als ich das erste Mal auf das Problem stieß. Eine Erklärung dessen, was mit dieser Lösung nicht in Ordnung ist, wird geschätzt. Danke im Voraus. –

1

Weil Sie Integer-Division machen.

Wie @Noldorin sagt, wenn beide Operatoren ganze Zahlen sind, dann ist Integer-Division verwendet.

Das Ergebnis 0,33333333 kann nicht als eine ganze Zahl dargestellt werden, wird daher nur der ganzzahlige Teil (0) dem Ergebnis zugeordnet.

Wenn einer der Operatoren ein double/float ist, dann wird Gleitkommaarithmetik stattfinden. Aber Sie werden das gleiche Problem haben, wenn Sie das tun:

int n = 1.0/3.0; 
1

Weil es 1 und 3 als ganze Zahlen behandelt, damit das Ergebnis Abrundung auf 0, so dass es eine ganze Zahl ist.

Um das Ergebnis der Sie suchen zu erhalten, explizit Java sagen, dass die Zahlen verdoppelt sind wie folgt:

double g = 1.0/3.0; 
-1

die 1 Mache einen Schwimmer und Division schweben

public static void main(String d[]){ 
    double g=1f/3; 
    System.out.printf("%.2f",g); 
} 
12

1/3 verwendet werden verwendet Integer-Division, da beide Seiten Ganzzahlen sind.

Sie müssen mindestens eine von ihnen float oder double sein.

Wenn Sie die Werte im Quellcode wie Ihre Frage eingeben, können Sie 1.0/3; Die 1.0 ist ein Doppel.

Wenn Sie die Werte von anderswo bekommen können Sie (double) verwenden, um die int in eine double einzuschalten.

int x = ...; 
int y = ...; 
double value = ((double) x)/y; 
2

sollten Sie

double g=1.0/3; 

oder

double g=1/3.0; 

Integer-Division liefert integer verwenden.

0

Viele andere haben es versäumt, die wirkliche Problem hinweisen:

Eine Operation auf nur ganze Zahlen wirft das Ergebnis der Operation auf eine ganze Zahl.

Dies bedeutet zwangsläufig, dass Gleitkomma Ergebnisse, dass könnte als Integer angezeigt werden (LOP aus dem Dezimalteil) abgeschnitten.

Was ist Gießen (Typumwandlung/Typumwandlung) Sie fragen?

Es variiert bei der Umsetzung der Sprache, aber Wikipedia hat eine ziemlich umfassende Sicht, und es spricht auch über Zwang, die eine zentrale Information bei der Beantwortung Ihrer Frage ist.

http://en.wikipedia.org/wiki/Type_conversion

1

Die Umwandlung in JAVA ist ziemlich einfach, aber brauchen ein gewisses Verständnis. Wie in der JLS erklärt für integer operations:

Wenn ein ganze Zahl Operator andere als ein Verschiebungs-Operator mindestens eine Operand vom Typ lange ist, dann wird die Operation durchgeführt, 64-Bit-Genauigkeit verwendet wird, und das Ergebnis der numerischen Operator ist vom Typ lang. Wenn der andere Operand nicht lang ist, wird er zuerst erweitert (§5.1.5), um durch numerische Werbung (§5.6) lang zu schreiben.

Und ein Beispiel ist immer der beste Weg, die JLS zu übersetzen;)

int + long -> long 
int(1) + long(2) + int(3) -> long(1+2) + long(3) 

Andernfalls wird die Operation durchgeführt wird 32-Bit-Genauigkeit mit, und das Ergebnis der numerischen Operator vom Typ int. Wenn einer der beiden Operanden kein int ist, wird er zuerst durch numerische Heraufstufung auf int erweitert.

short + int -> int + int -> int 

Ein kleines Beispiel Eclipse zu zeigen, dass auch ein Zusatz von zwei short s nicht so einfach sein wird:

short s = 1; 
s = s + s; <- Compiling error 

//possible loss of precision 
// required: short 
// found: int 

Dies wird benötigt, um einen Gussteil mit einem möglichen Verlust an Präzision.

Das gleiche gilt für die floating point operators

Wenn mindestens einer der Operanden auf einen numerischen Operator vom Typ double, dann wird die Operation als wahr durch 64-Bit unter Verwendung von arithmetischen Gleitkommaoperationen und Das Ergebnis des numerischen Operators ist ein Wert vom Typ double. Wenn der andere Operand kein Double ist, wird er zuerst erweitert (§5.1.5), um Double by numeric promotion (§5.6) einzugeben.

Also die Förderung erfolgt über den Float in Doppel.

Und die Mischung aus beiden Ganzzahl- und Fließwert Ergebniswerte in floating als die

Wenn mindestens einer der Operanden an einen Binäroperator von Fließkommatyp ist, dann ist die Operation eine Fließ- Punktoperation, auch wenn die andere Integral ist.

Dies ist für binäre Operatoren wahr, aber nicht für „Zuweisungsoperator“ wie +=

Ein einfaches Ausführungsbeispiel genug ist, dies zu beweisen

int i = 1; 
i += 1.5f; 

Der Grund dafür ist, dass es eine implizite Umwandlung ist hier erfolgt, wird diese ausführen werden wie

i = (int) i + 1.5f 
i = (int) 2.5f 
i = 2 
-1

(1/3) bedeutet Integer divisio n, deshalb können Sie von dieser Division keinen Dezimalwert erhalten. Um dieses Problem zu lösen, verwenden Sie:

public static void main(String[] args) { 
     double g = 1.0/3; 
     System.out.printf("%.2f", g); 
    }