Ist es in Java effizienter, Byte oder Short anstelle von int und float anstelle von double zu verwenden?


91

Mir ist aufgefallen, dass ich immer int und double verwendet habe, egal wie klein oder groß die Zahl sein muss. Ist es in Java effizienter, byteoder shortanstelle von intund floatanstelle von zu verwenden double?

Nehmen wir also an, ich habe ein Programm mit vielen Ints und Doubles. Wäre es wert, meine Ints in Bytes oder Shorts zu ändern, wenn ich wüsste, dass die Nummer passen würde?

Ich weiß, dass Java keine vorzeichenlosen Typen hat, aber kann ich noch etwas tun, wenn ich wüsste, dass die Zahl nur positiv ist?

Mit effizient meine ich meistens die Verarbeitung. Ich würde annehmen, dass der Garbage Collector viel schneller wäre, wenn alle Variablen halb so groß wären und dass die Berechnungen wahrscheinlich auch etwas schneller wären. (Ich denke, da ich an Android arbeite, muss ich mir auch etwas Sorgen um RAM machen)

(Ich würde annehmen, dass der Garbage Collector nur Objekte und keine Grundelemente behandelt, aber dennoch alle Grundelemente in verlassenen Objekten löscht, oder?)

Ich habe es mit einer kleinen Android-App versucht, aber ich habe überhaupt keinen Unterschied bemerkt. (Obwohl ich nichts "wissenschaftlich" gemessen habe.)

Bin ich falsch in der Annahme, dass es schneller und effizienter sein sollte? Ich würde es hassen, alles in einem riesigen Programm zu ändern, um herauszufinden, dass ich meine Zeit verschwendet habe.

Wäre es von Anfang an wert, wenn ich ein neues Projekt starte? (Ich meine, ich denke, jedes kleine bisschen würde helfen, aber wenn ja, warum scheint es nicht so, als ob es jemand tut.)

Antworten:


107

Bin ich falsch in der Annahme, dass es schneller und effizienter sein sollte? Ich würde es hassen, alles in einem riesigen Programm zu ändern, um herauszufinden, dass ich meine Zeit verschwendet habe.

Kurze Antwort

Ja, du liegst falsch. In den meisten Fällen macht es wenig Platz.

Es lohnt sich nicht , dies zu optimieren ... es sei denn, Sie haben eindeutige Beweise dafür, dass eine Optimierung erforderlich ist. Und wenn Sie insbesondere die Speichernutzung von Objektfeldern optimieren müssen, müssen Sie wahrscheinlich andere (effektivere) Maßnahmen ergreifen.

Längere Antwort

Die Java Virtual Machine modelliert Stapel und Objektfelder mithilfe von Offsets, die (tatsächlich) ein Vielfaches einer primitiven 32-Bit-Zellengröße sind. Wenn Sie also eine lokale Variable oder ein Objektfeld als (sagen wir) a deklarieren byte, wird die Variable / das Feld genau wie eine in einer 32-Bit-Zelle gespeichert int.

Hiervon gibt es zwei Ausnahmen:

  • longund doubleWerte erfordern 2 primitive 32-Bit-Zellen
  • Arrays primitiver Typen werden in gepackter Form dargestellt, so dass (zum Beispiel) ein Array von Bytes 4 Bytes pro 32-Bit-Wort enthält.

Es könnte sich also lohnen, die Verwendung von longund double... und große Anordnungen von Grundelementen zu optimieren . Aber im Allgemeinen nein.

Theoretisch könnte eine JIT dies optimieren, aber in der Praxis habe ich noch nie von einer JIT gehört, die dies tut. Ein Hindernis besteht darin, dass die JIT normalerweise erst ausgeführt werden kann, nachdem Instanzen der zu kompilierenden Klasse erstellt wurden. Wenn die JIT das Speicherlayout optimieren würde, könnten Sie zwei (oder mehr) "Geschmacksrichtungen" von Objekten derselben Klasse haben ... und das würde große Schwierigkeiten bereiten.


Wiederholung

Wenn man sich die Benchmark-Ergebnisse in der Antwort von @ meriton ansieht, scheint es, dass die Verwendung von shortund byteanstelle von inteine Leistungsstrafe für die Multiplikation verursacht. Wenn Sie die Operationen isoliert betrachten, ist die Strafe in der Tat erheblich. (Sie sollten sie nicht isoliert betrachten ... aber das ist ein anderes Thema.)

Ich denke, die Erklärung ist, dass JIT die Multiplikationen wahrscheinlich mit jeweils 32-Bit-Multiplikationsbefehlen durchführt. Aber in dem byteund shortFall, führt er zusätzliche Anweisungen , um das Zwischenprodukt 32 - Bit - Wert in einem zu überführen byteoder shortin jeder Schleifeniteration. (Theoretisch könnte diese Konvertierung einmal am Ende der Schleife durchgeführt werden ... aber ich bezweifle, dass der Optimierer dies herausfinden kann.)

Dies deutet jedoch auf ein weiteres Problem beim Umschalten auf shortund byteals Optimierung hin. Dies könnte die Leistung beeinträchtigen ... in einem Algorithmus, der arithmetisch und rechenintensiv ist.


30
+1 nicht optimieren, es sei denn, Sie haben eindeutige Hinweise auf ein Leistungsproblem
Bohemian

Ähm, warum muss die JVM auf die JIT-Kompilierung warten, um das Speicherlayout einer Klasse zu packen? Da die Feldtypen in die Klassendatei geschrieben werden, konnte die JVM dann beim Laden der Klasse kein Speicherlayout auswählen und dann die Feldnamen als Byte und nicht als Wortversatz auflösen?
Meriton

@meriton - Ich bin mir ziemlich sicher, dass Objektlayouts zum Ladezeitpunkt der Klasse festgelegt werden und sich danach nicht mehr ändern. Siehe den "Kleingedruckten" Teil meiner Antwort. Wenn sich die tatsächlichen Speicherlayouts während der JIT-Erstellung des Codes ändern würden, wäre es für die JVM sehr schwierig, damit umzugehen. (Als ich sagte , dass die JIT das Layout optimieren könnte , ist das hypothetisch und unpraktisch ... was erklären könnte, warum ich noch nie von einer JIT gehört habe, die dies tatsächlich tut.)
Stephen C

Ich weiß. Ich wollte nur darauf hinweisen, dass eine JVM das Speicherlayout möglicherweise vorher optimiert, dh zum Laden der Klasse, obwohl die Speicherlayouts nach dem Erstellen von Objekten schwer zu ändern sind. Anders ausgedrückt, dass die JVM-Spezifikation das Verhalten einer JVM mit Wortversätzen beschreibt, bedeutet nicht unbedingt, dass eine JVM auf diese Weise implementiert werden muss - obwohl dies höchstwahrscheinlich der Fall ist.
Meriton

@meriton - In der JVM-Spezifikation geht es um "Wortversätze für virtuelle Maschinen" in lokalen Frames / Objekten. Wie diese auf physische Maschinenversätze abgebildet werden, ist NICHT angegeben. In der Tat kann es nicht spezifiziert werden ... da möglicherweise hardwarespezifische Anforderungen an die Feldausrichtung bestehen.
Stephen C

29

Dies hängt von der Implementierung der JVM sowie der zugrunde liegenden Hardware ab. Die meiste moderne Hardware ruft keine einzelnen Bytes aus dem Speicher (oder sogar aus dem Cache der ersten Ebene) ab, dh die Verwendung der kleineren primitiven Typen reduziert im Allgemeinen den Speicherbandbreitenverbrauch nicht. Ebenso haben moderne CPUs eine Wortgröße von 64 Bit. Sie können Operationen mit weniger Bits ausführen, aber das funktioniert, indem die zusätzlichen Bits verworfen werden, was auch nicht schneller ist.

Der einzige Vorteil besteht darin, dass kleinere primitive Typen zu einem kompakteren Speicherlayout führen können, insbesondere bei Verwendung von Arrays. Dies spart Speicherplatz, wodurch die Referenzlokalität verbessert werden kann (wodurch die Anzahl der Cache-Fehler verringert wird) und der Aufwand für die Speicherbereinigung verringert wird.

Im Allgemeinen ist die Verwendung der kleineren primitiven Typen jedoch nicht schneller.

Um dies zu demonstrieren, sehen Sie sich den folgenden Benchmark an:

package tools.bench;

import java.math.BigDecimal;

public abstract class Benchmark {

    final String name;

    public Benchmark(String name) {
        this.name = name;
    }

    abstract int run(int iterations) throws Throwable;

    private BigDecimal time() {
        try {
            int nextI = 1;
            int i;
            long duration;
            do {
                i = nextI;
                long start = System.nanoTime();
                run(i);
                duration = System.nanoTime() - start;
                nextI = (i << 1) | 1; 
            } while (duration < 100000000 && nextI > 0);
            return new BigDecimal((duration) * 1000 / i).movePointLeft(3);
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }   

    @Override
    public String toString() {
        return name + "\t" + time() + " ns";
    }

    public static void main(String[] args) throws Exception {
        Benchmark[] benchmarks = {
            new Benchmark("int multiplication") {
                @Override int run(int iterations) throws Throwable {
                    int x = 1;
                    for (int i = 0; i < iterations; i++) {
                        x *= 3;
                    }
                    return x;
                }
            },
            new Benchmark("short multiplication") {                   
                @Override int run(int iterations) throws Throwable {
                    short x = 0;
                    for (int i = 0; i < iterations; i++) {
                        x *= 3;
                    }
                    return x;
                }
            },
            new Benchmark("byte multiplication") {                   
                @Override int run(int iterations) throws Throwable {
                    byte x = 0;
                    for (int i = 0; i < iterations; i++) {
                        x *= 3;
                    }
                    return x;
                }
            },
            new Benchmark("int[] traversal") {                   
                @Override int run(int iterations) throws Throwable {
                    int[] x = new int[iterations];
                    for (int i = 0; i < iterations; i++) {
                        x[i] = i;
                    }
                    return x[x[0]];
                }
            },
            new Benchmark("short[] traversal") {                   
                @Override int run(int iterations) throws Throwable {
                    short[] x = new short[iterations];
                    for (int i = 0; i < iterations; i++) {
                        x[i] = (short) i;
                    }
                    return x[x[0]];
                }
            },
            new Benchmark("byte[] traversal") {                   
                @Override int run(int iterations) throws Throwable {
                    byte[] x = new byte[iterations];
                    for (int i = 0; i < iterations; i++) {
                        x[i] = (byte) i;
                    }
                    return x[x[0]];
                }
            },
        };
        for (Benchmark bm : benchmarks) {
            System.out.println(bm);
        }
    }
}

welches auf meinem etwas alten Notizbuch gedruckt wird (Leerzeichen hinzufügen, um Spalten anzupassen):

int       multiplication    1.530 ns
short     multiplication    2.105 ns
byte      multiplication    2.483 ns
int[]     traversal         5.347 ns
short[]   traversal         4.760 ns
byte[]    traversal         2.064 ns

Wie Sie sehen können, sind die Leistungsunterschiede recht gering. Die Optimierung von Algorithmen ist weitaus wichtiger als die Wahl des primitiven Typs.


3
Anstatt "vor allem bei der Verwendung von Arrays" zu sagen, könnte es einfacher sein, dies zu sagen, shortund sie bytesind effizienter, wenn sie in Arrays gespeichert werden, die groß genug sind, um eine Rolle zu spielen (je größer das Array, byte[2]desto größer der Effizienzunterschied; a ist möglicherweise größer oder weniger effizient als ein int[2], aber nicht genug, um eine Rolle zu spielen), aber dass einzelne Werte effizienter gespeichert werden als int.
Supercat

2
Was ich überprüft habe: Diese Benchmarks verwendeten immer ein int ('3') als Faktor oder Zuweisungsoperanden (die Schleifenvariante, dann umgewandelt). Was ich getan habe, war, typisierte Faktoren / Zuweisungsoperanden abhängig vom Wertetyp zu verwenden: int mult 76,481 ns int mult (typisiert) 72,581 ns short mult 87,908 ns short mult (typisiert) 90,772 ns byte mult 87,859 ns byte mult (typisiert) 89,524 ns int [] trav 88.905 ns int [] trav (getippt) 89.126 ns kurz [] trav 10.563 ns kurz [] trav (getippt) 10.039 ns byte [] trav 8.356 ns byte [] trav (getippt) 8.338 ns Ich nehme an, es gibt eine viel unnötiges Casting. Diese Tests wurden auf einem Android-Tab ausgeführt.
Bondax

5

Die Verwendung von byteanstelle von intkann die Leistung steigern, wenn Sie sie in großer Menge verwenden. Hier ist ein Experiment:

import java.lang.management.*;

public class SpeedTest {

/** Get CPU time in nanoseconds. */
public static long getCpuTime() {
    ThreadMXBean bean = ManagementFactory.getThreadMXBean();
    return bean.isCurrentThreadCpuTimeSupported() ? bean
            .getCurrentThreadCpuTime() : 0L;
}

public static void main(String[] args) {
    long durationTotal = 0;
    int numberOfTests=0;

    for (int j = 1; j < 51; j++) {
        long beforeTask = getCpuTime();
        // MEASURES THIS AREA------------------------------------------
        long x = 20000000;// 20 millions
        for (long i = 0; i < x; i++) {
                           TestClass s = new TestClass(); 

        }
        // MEASURES THIS AREA------------------------------------------
        long duration = getCpuTime() - beforeTask;
        System.out.println("TEST " + j + ": duration = " + duration + "ns = "
                + (int) duration / 1000000);
        durationTotal += duration;
        numberOfTests++;
    }
    double average = durationTotal/numberOfTests;
    System.out.println("-----------------------------------");
    System.out.println("Average Duration = " + average + " ns = "
            + (int)average / 1000000 +" ms (Approximately)");


}

}}

Diese Klasse testet die Geschwindigkeit beim Erstellen eines neuen TestClass. Jeder Test macht es 20 Millionen Mal und es gibt 50 Tests.

Hier ist die Testklasse:

 public class TestClass {
     int a1= 5;
     int a2= 5; 
     int a3= 5;
     int a4= 5; 
     int a5= 5;
     int a6= 5; 
     int a7= 5;
     int a8= 5; 
     int a9= 5;
     int a10= 5; 
     int a11= 5;
     int a12=5; 
     int a13= 5;
     int a14= 5; 
 }

Ich habe die SpeedTestKlasse geleitet und am Ende Folgendes bekommen:

 Average Duration = 8.9625E8 ns = 896 ms (Approximately)

Jetzt ändere ich die Ints in der TestClass in Bytes und führe sie erneut aus. Hier ist das Ergebnis:

 Average Duration = 6.94375E8 ns = 694 ms (Approximately)

Ich glaube, dieses Experiment zeigt, dass die Verwendung von Byte anstelle von int die Effizienz steigern kann, wenn Sie eine große Anzahl von Variablen instanziieren


4
Beachten Sie, dass dieser Benchmark nur die mit der Zuordnung und dem Bau verbundenen Kosten misst und nur den Fall einer Klasse mit vielen einzelnen Feldern. Wenn Arithmetik- / Aktualisierungsoperationen für die Felder ausgeführt wurden, deuten die Ergebnisse von @ meriton darauf hin, bytedass >> langsamer << als sein könnte int.
Stephen C

Es stimmt, ich hätte es besser formulieren sollen, um es zu klären.
WVrock

2

Byte wird im Allgemeinen als 8 Bit betrachtet. kurz wird allgemein als 16 Bit angesehen.

In einer "reinen" Umgebung, die nicht Java ist, da die gesamte Implementierung von Bytes und Longs, Shorts und anderen lustigen Dingen im Allgemeinen vor Ihnen verborgen ist, nutzt Byte den Speicherplatz besser aus.

Ihr Computer ist jedoch wahrscheinlich nicht 8-Bit und wahrscheinlich nicht 16-Bit. Dies bedeutet, dass, um insbesondere 16 oder 8 Bits zu erhalten, auf "Tricks" zurückgegriffen werden muss, die Zeit verschwenden, um vorzutäuschen, dass es bei Bedarf auf diese Typen zugreifen kann.

Zu diesem Zeitpunkt hängt es davon ab, wie die Hardware implementiert ist. Wie ich jedoch gelernt habe, wird die beste Geschwindigkeit erreicht, wenn Dinge in Blöcken gespeichert werden, die für Ihre CPU bequem zu verwenden sind. Ein 64-Bit-Prozessor beschäftigt sich gerne mit 64-Bit-Elementen, und alles andere erfordert oft "technische Magie", um so zu tun, als würde er sich gerne mit ihnen befassen.


3
Ich bin mir nicht sicher, was Sie unter "technischer Magie" verstehen ... Die meisten / alle modernen Prozessoren haben schnelle Anweisungen, um ein Byte zu laden und mit Vorzeichen zu erweitern, eines aus einem Register voller Breite zu speichern und Bytebreite zu tun oder Arithmetik mit kurzer Breite in einem Teil eines Registers mit voller Breite. Wenn Sie Recht hätten, wäre es sinnvoll, wenn möglich, alle Ints durch Longs auf einem 64-Bit-Prozessor zu ersetzen.
Ed Staub

Ich kann mir vorstellen, dass das wahr ist. Ich erinnere mich nur, dass in dem von uns verwendeten Motorola 68k-Simulator die meisten Operationen mit 16-Bit-Werten arbeiten konnten, ohne mit 32-Bit- oder 64-Bit-Werten. Ich dachte, dass dies bedeutet, dass Systeme eine bevorzugte Wertgröße haben, die sie optimal abrufen können. Obwohl ich mir vorstellen kann, dass moderne 64-Bit-Prozessoren 8-Bit-, 16-Bit-, 32-Bit- und 64-Bit-Prozessoren gleichermaßen einfach abrufen können, handelt es sich in diesem Fall nicht um eine Ausgabe. Vielen Dank für den Hinweis.
Dmitry

"... wird allgemein als ... angesehen" - Tatsächlich wird eindeutig >> eindeutig << angegeben, um diese Größen zu sein. In Java. Und der Kontext dieser Frage ist Java.
Stephen C

Eine große Anzahl von Prozessoren verwendet sogar die gleiche Anzahl von Zyklen, um Daten zu bearbeiten und auf diese zuzugreifen, die keine Wortgröße haben. Es lohnt sich also nicht, sich darüber Gedanken zu machen, es sei denn, Sie messen auf einer bestimmten JVM und Plattform.
Drrob

Ich versuche allgemein zu sagen. Das heißt, ich bin mir über Javas Standard in Bezug auf die Bytegröße nicht sicher, aber an diesem Punkt bin ich ziemlich überzeugt, dass Java sie nicht mit einem 10-Fuß-Pol berühren möchte, wenn ein Ketzer nicht 8-Bit-Bytes entscheidet. Einige Prozessoren erfordern jedoch eine Multibyte-Ausrichtung. Wenn die Java-Plattform sie unterstützt, müssen die Schritte langsamer ausgeführt werden, um den Umgang mit diesen kleineren Typen zu ermöglichen, oder sie können magisch mit größeren Darstellungen dargestellt werden, als Sie angefordert haben. Das bevorzugt immer int gegenüber anderen Typen, da es immer die Lieblingsgröße des Systems verwendet.
Dmitry

2

Einer der Gründe für die geringere Leistung von Short / Byte / Char ist der Mangel an direkter Unterstützung für diese Datentypen. Durch direkte Unterstützung bedeutet dies, dass in den JVM-Spezifikationen kein Befehlssatz für diese Datentypen erwähnt wird. Anweisungen wie Speichern, Laden, Hinzufügen usw. haben Versionen für den Datentyp int. Sie haben jedoch keine Versionen für short / byte / char. Betrachten Sie zB den folgenden Java-Code:

void spin() {
 int i;
 for (i = 0; i < 100; i++) {
 ; // Loop body is empty
 }
}

Gleiches wird wie unten in Maschinencode umgewandelt.

0 iconst_0 // Push int constant 0
1 istore_1 // Store into local variable 1 (i=0)
2 goto 8 // First time through don't increment
5 iinc 1 1 // Increment local variable 1 by 1 (i++)
8 iload_1 // Push local variable 1 (i)
9 bipush 100 // Push int constant 100
11 if_icmplt 5 // Compare and loop if less than (i < 100)
14 return // Return void when done

Erwägen Sie nun, int wie unten in short zu ändern.

void sspin() {
 short i;
 for (i = 0; i < 100; i++) {
 ; // Loop body is empty
 }
}

Der entsprechende Maschinencode ändert sich wie folgt:

0 iconst_0
1 istore_1
2 goto 10
5 iload_1 // The short is treated as though an int
6 iconst_1
7 iadd
8 i2s // Truncate int to short
9 istore_1
10 iload_1
11 bipush 100
13 if_icmplt 5
16 return

Wie Sie sehen können, wird zur Manipulation des kurzen Datentyps weiterhin die Anweisungsversion des Datentyps int verwendet und bei Bedarf explizit in den Datentyp int konvertiert. Aufgrund dessen wird die Leistung jetzt reduziert.

Als Grund für die Nichtunterstützung wird nun folgender Grund angeführt:

Die Java Virtual Machine bietet die direkteste Unterstützung für Daten vom Typ int. Dies ist teilweise im Vorgriff auf effiziente Implementierungen der Operandenstapel und lokalen Variablenarrays der Java Virtual Machine. Es wird auch durch die Häufigkeit von int-Daten in typischen Programmen motiviert. Andere integrale Typen haben weniger direkte Unterstützung. Es gibt beispielsweise keine Byte-, Zeichen- oder Kurzversionen zum Speichern, Laden oder Hinzufügen von Anweisungen.

Zitiert aus der hier vorhandenen JVM-Spezifikation (Seite 58).


Dies sind zerlegte Bytecodes; dh virtuelle JVM- Anweisungen. Sie werden vom javacCompiler nicht optimiert , und Sie können daraus keine verlässlichen Rückschlüsse auf die Leistung des Programms im wirklichen Leben ziehen. Der JIT-Compiler kompiliert diese Bytecodes zu tatsächlichen nativen Maschinenanweisungen und führt dabei einige ziemlich ernsthafte Optimierungen durch. Wenn Sie die Leistung des Codes analysieren möchten , müssen Sie die Anweisungen für den nativen Code überprüfen. (Und es ist kompliziert, weil Sie das Timing-Verhalten einer mehrstufigen x86_64-Pipeline berücksichtigen müssen.)
Stephen C

Ich glaube, die Java-Spezifikationen müssen von den Java-Implementierern implementiert werden. Ich glaube also nicht, dass auf dieser Ebene weitere Optimierungen vorgenommen werden. Jedenfalls könnte ich mich auch völlig irren. Bitte teilen Sie einen Referenzlink mit, um Ihre Aussage zu unterstützen.
Manish Bansal

Nun, hier ist eine Tatsache, die meine Aussage stützt. Sie werden keine (glaubwürdigen) Zeitangaben finden, die Ihnen sagen, wie viele Taktzyklen jeder JVM-Bytecode-Befehl benötigt. Sicherlich nicht von Oracle oder anderen JVM-Anbietern veröffentlicht. Lesen Sie auch stackoverflow.com/questions/1397009
Stephen C

Ich habe ein altes (2008) Papier gefunden, in dem jemand versucht hat, ein plattformunabhängiges Modell zur Vorhersage der Leistung von Bytecode-Sequenzen zu entwickeln. Sie behaupten, dass ihre Vorhersagen im Vergleich zu RDTSC-Messungen auf einem Pentium um 25% abweichen. Und sie haben die JVM mit deaktivierter JIT-Kompilierung ausgeführt! Referenz: sciencedirect.com/science/article/pii/S1571066108004581
Stephen C

Ich bin hier nur verwirrt. Unterstützt meine Antwort nicht die Fakten, die Sie im Abschnitt "Wiederholung" angegeben haben?
Manish Bansal

0

Der Unterschied ist kaum spürbar! Es ist eher eine Frage des Designs, der Angemessenheit, der Einheitlichkeit, der Gewohnheit usw. Manchmal ist es nur eine Frage des Geschmacks. Wenn Sie sich nur darum kümmern, dass Ihr Programm in Betrieb genommen wird und das Ersetzen eines floatdurch ein Programm ersetzt, intwürde dies die Korrektheit nicht beeinträchtigen. Ich sehe keinen Vorteil darin, das eine oder andere zu wählen, es sei denn, Sie können nachweisen, dass die Verwendung eines der beiden Typen die Leistung verändert. Das Optimieren der Leistung basierend auf Typen, die sich in 2 oder 3 Bytes unterscheiden, ist wirklich das Letzte, was Sie beachten sollten. Donald Knuth hat einmal gesagt: "Vorzeitige Optimierung ist die Wurzel allen Übels" (nicht sicher, ob er es war, bearbeiten Sie, wenn Sie die Antwort haben).


5
Nit: A float kann nicht alle ganzen Zahlen einer intDose darstellen. a kann auch intkeinen nicht ganzzahligen Wert darstellen, der dies floatkann. Das heißt, während alle int-Werte eine Teilmenge langer Werte sind, ist ein int keine Teilmenge eines float und ein float ist keine Teilmenge eines int.

Ich erwarte, dass der Antwortende schreiben soll substituting a float for a double, wenn ja, sollte der Antwortende die Antwort bearbeiten. Wenn nicht, sollte der Antwortende beschämt den Kopf hängen lassen und aus den von @pst genannten Gründen und aus vielen anderen Gründen zu den Grundlagen zurückkehren.
High Performance Mark

@HighPerformanceMark Nein, ich habe int und float gesetzt, weil ich das gedacht habe. Meine Antwort ist nicht spezifisch für Java, obwohl ich dachte, C ... Es soll allgemein sein. Mein Kommentar, den du dort bekommen hast.
Herr
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.