2016-03-27 8 views
0

In Java, wenn ich so etwas wie dieses ich eine Ausgabe vonWie behandelt Java die Genauigkeit über mehrere Typen hinweg?

1.0 

oder mit

System.out.println(((byte)1)*'A'); 

ich eine Ausgabe von

65 

erhalten erhalten

System.out.println(1.0f*1l)); 

drucken In beiden Fällen ist einer der Typen größer als der andere. Longs sind 64 Bits, Floats sind 32 Bits und Bytes sind 8 Bits, während Zeichen 16 Bits sind. Trotzdem gibt Java das Ergebnis im kleineren Typ aus. Wäre dies nicht als Verlust der Präzision zu betrachten?

+2

Dies wird ausführlich in der Java Language Specification behandelt. Es gibt ein ganzes Kapitel [Conversions and Contexts] (http://docs.oracle.com/javase/specs/jls/se8/html/jls-5.html). –

+1

https://docs.oracle.com/javase/specs/jls/se8/html/jls-5.html#jls-5.6.2 –

Antwort

4

Java-Sprachspezifikation enthält eine Liste von Regeln, die den Ergebnistyp basierend auf den Operandentypen steuern.

Insbesondere Abschnitt 4.2.4 sagt, dass

Wenn mindestens einer der Operanden in einen binären Operator ist der Gleitkommawert-Typ, dann ist die Operation eine Gleitkommaoperation, auch wenn die andere sind integraler Bestandteil.

was erklärt, warum float "gewinnt" gegen eine long.

Die Ganzzahlarithmetik wird in Abschnitt 5.6.2 erläutert. Insbesondere heißt es, dass

Widening primitive Umwandlung (§5.1.2) angewandt wird, konvertieren entweder oder beiden Operanden wie durch die folgenden Regeln festgelegt:

• Wenn einer der Operanden vom Typ double, die andere wird in double konvertiert. Wenn der eine Operand vom Typ float ist, wird der andere in float konvertiert. Wenn der Operand vom Typ long ist, wird der andere in long konvertiert.

• Ansonsten werden beide Operanden in den Typ int konvertiert.

Deshalb ist in Ihrem zweiten Beispiel das Ergebnis, 65, vom Typ int.

0

Java erweitert den Typ basierend auf dem Bereich der möglichen Werte. Dies bedeutet, dass float als breiter betrachtet wird als long.

Auch ganzzahlige Operationen, die nicht long sind, werden als int ausgeführt. A byte * char ist ein int

0

Du über Binary Numeric Promotion (JLS 5.6.2) (Hervorhebung von mir) zu fragen:

Wenn ein Bediener binäre numerische Förderung auf ein Paar von Operanden gilt, von denen jedes einen Wert bezeichnen müssen, die in einen numerischen Typ konvertierbar ist, gelten die folgenden Regeln in der Reihenfolge:

  1. Wenn irgendein Operand eines Referenztyp ist, um es zu unboxing Umwandlung unterzogen wird (§5.1.8).
  2. Widening primitive Umwandlung (§5.1.2) wird entweder oder beiden Operanden zu konvertieren, wie durch die folgenden Regeln festgelegt:
    • Falls einer der Operanden des Typs double, die andere an double umgewandelt werden.
    • Andernfalls , wenn einer der Operanden vom Typ float ist, wird der andere in float konvertiert.
    • Andernfalls, wenn einer der Operanden vom Typ long ist, wird der andere in long konvertiert.
    • Andernfalls werden beide Operanden in den Typ int konvertiert.

Der Ausdruck 1.0f*1l ist ein float und long, so dass die auf eine longfloat umgewandelt wird.

Der Ausdruck ((byte)1)*'A' ist ein byte und eine char, so dass sie sowohl auf umgewandelt int.

0

Zusätzlich zu den anderen Antworten, die die Regeln im Detail buchstabieren, denke ich, es ist auch eine Überlegung wert, warum es so sein sollte. Angenommen, Sie tun

Die wahre mathematische Antwort auf diese Multiplikation ist 5.4. Wenn also die Antwort long wäre, müsste es 5L sein (5 ist die nächste ganze Zahl bis 5,4). Wegen dieser Art von Sache macht es viel mehr Sinn für das Ergebnis der Multiplikation eines Gleitkommawertes mit einer ganzen Zahl als Gleitkommawert. Ich denke, dass es auf Stack Overflow viele weitere Fragen dazu geben würde, wenn die folgende Codezeile 5 gedruckt würde.

System.out.println(2.7F * 2L); 

In der Tat druckt es 5.4.

Es ist auch sinnvoll, dass alle Operationen zwischen Integer-Typen (außer long) mit int durchgeführt werden. Schließlich wird ein byte in der Regel als ein kleines Paket von Daten gedacht, und ein char wird normalerweise als ein Zeichen gedacht. Aus diesen Perspektiven multipliziert byte oder char Werte ist nicht wirklich sinnvoll. Es macht viel mehr Sinn, die Regeln einfach zu halten und einfach die Operationen mit int durchzuführen.

Verwandte Themen