Wann sollte ich das Schlüsselwort "strictfp" in Java verwenden?

258

Ich habe nachgeschlagen, was dies bewirkt, aber hat jemand tatsächlich ein Beispiel dafür, wann Sie das strictfpSchlüsselwort in Java verwenden würden? Hat jemand tatsächlich eine Verwendung dafür gefunden?

Würde es irgendwelche Nebenwirkungen geben, wenn ich es nur auf alle meine Gleitkommaoperationen anwenden würde?

GBa
quelle
1
Immer, es sei denn, Sie benötigen die Leistung tatsächlich mehr als die Reproduzierbarkeit.
Antimon
1
@ Antimon - oder die Präzision / Korrektheit. x86 / x64 verwenden beispielsweise intern 80-Bit-Gleitkommaregister, sodass das Ergebnis für eine lange Berechnung ohne strictfp genauer ist.
Robert Fraser
1
@ Robert Tatsächlich garantiert die Spezifikation eine begrenzte Präzision der Mantisse. Der einzige Unterschied besteht darin, dass möglicherweise eine größere Exponentengenauigkeit als normal verwendet wird, was in seltenen Fällen aufgrund der doppelten Rundung Unterschiede aufweist.
Antimon
Ich denke, dass zusätzlich zu der Option, diesen nützlichen Modifikator rund um das Gelenk zu verteilen, neue sfloat & sdouble primitive strictfp-Datentypen eine gute Idee sein könnten.
TheRiley

Antworten:

274

Strictfp stellt sicher, dass Sie auf jeder Plattform genau die gleichen Ergebnisse aus Ihren Gleitkommaberechnungen erhalten. Wenn Sie strictfp nicht verwenden, kann die JVM-Implementierung, sofern verfügbar, zusätzliche Präzision verwenden.

Aus dem JLS :

Innerhalb eines FP-strengen Ausdrucks müssen alle Zwischenwerte Elemente des Float-Wertesatzes oder des Doppelwertsatzes sein, was bedeutet, dass die Ergebnisse aller FP-strengen Ausdrücke diejenigen sein müssen, die von der IEEE 754-Arithmetik für Operanden vorhergesagt werden, die im Einzel- und Doppelformat dargestellt werden . Innerhalb eines Ausdrucks, der nicht FP-streng ist, wird einer Implementierung ein gewisser Spielraum eingeräumt, um einen erweiterten Exponentenbereich zur Darstellung von Zwischenergebnissen zu verwenden. Der Nettoeffekt besteht grob gesagt darin, dass eine Berechnung in Situationen, in denen die ausschließliche Verwendung des Float-Wertesatzes oder des Doppelwertsatzes zu einem Über- oder Unterlauf führen kann, "die richtige Antwort" liefern kann.

Mit anderen Worten, es geht darum sicherzustellen, dass Write-Once-Run-Anywhere tatsächlich Write-Once-Get-Equally-Wrong-Results-Everywhere bedeutet .

Mit strictfp sind Ihre Ergebnisse portabel, ohne sie sind sie mit größerer Wahrscheinlichkeit genau.

Dan Dyer
quelle
28
Verwenden Sie es für reproduzierbare wissenschaftliche Ergebnisse und bitgenaue Unit-Tests.
Aleksandr Dubinsky
1
"Wenn Sie strictfp nicht verwenden, kann die JVM-Implementierung, sofern verfügbar, zusätzliche Präzision verwenden" - das klingt nach einer schlechten Sache: P
AMDG
@ LinkTheProgrammer es kann sicherlich eine schlechte Sache sein
Tim
@ TimCastelijns Ich nehme an, Happy Wheels ist Ihre Referenz? Die Wiederholungen zeichnen Tastenanschläge auf. Aufgrund der Präzisionsvielfalt der FP-Math-Implementierung sind die Wiederholungen nur auf ähnlicher Hardware genau. Können Sie ein realistischeres Problem nennen, das durch die Variabilität der Gleitkomma-Mathematik verursacht wird? Ich kann mir vielleicht einen Partikelsimulator vorstellen, aber was noch?
AMDG
Das heißt also, wir sollten immer strictfp in der Produktion verwenden, wenn mehrere Plattformen beteiligt sind?
Beatrice
65

Wikipedia hat hier tatsächlich einen guten Artikel zu diesem Thema mit einem Link zur Java-Spezifikation.

Wenn Sie zwischen den Zeilen lesen, bedeutet dies strictfp, dass der JVM- und der JIT-Compiler die Lizenz haben, Ihre Gleitkommaberechnungen nach Belieben zu berechnen , wenn Sie dies nicht angeben . Im Interesse der Geschwindigkeit werden sie die Berechnung höchstwahrscheinlich an Ihren Prozessor delegieren. Mit strictfpon müssen die Berechnungen den IEEE 754-Arithmetikstandards entsprechen, was in der Praxis wahrscheinlich bedeutet, dass die JVM die Berechnung durchführt.

Warum sollten Sie also verwenden strictfp? Ein Szenario, das ich sehen kann, ist eine verteilte Anwendung (oder ein Multiplayer-Spiel), in der alle Gleitkommaberechnungen deterministisch sein müssen, unabhängig von der zugrunde liegenden Hardware oder CPU. Was ist der Kompromiss? Höchstwahrscheinlich Ausführungszeit.

MattK
quelle
5
"Ein erweiterter Exponentenbereich zur Darstellung von Zwischenergebnissen" ist keine "Lizenz zur Berechnung Ihrer Gleitkommaberechnungen nach Belieben", und in der Praxis verwenden sogar strictfpBerechnungen sogar eine nicht hilfreiche 8087-FPU. Es ist nur dann der Fall, dass ein wenig Sorgfalt erforderlich ist. Siehe stackoverflow.com/questions/18496560/…
Pascal Cuoq
Ich stimme @PascalCuoq bezüglich: "Lizenz zur Berechnung Ihrer Gleitkommaberechnungen nach Belieben " zu . Wenn überhaupt, scheint in diesem Fall das Gegenteil der Fall zu sein, da strictfpdie Einhaltung des IEEE 754-Standards sichergestellt ist (sodass Sie auf allen Plattformen das gleiche Ergebnis erzielen). Der einzige Nachteil, den ich sehen kann, ist, dass Sie möglicherweise die Vorteile einer wirklich guten FPU in Ihrer nativen Hardware verlieren.
Typeracer
25

Alles begann mit einer Geschichte,

Als Java von James Gosling, Herbert und dem Rest seines Teams entwickelt wurde. Sie hatten dieses verrückte Ding im Sinn, das Plattformunabhängigkeit genannt wurde . Sie wollten Eiche machen (Java)so viel besser, dass es auf jedem Computer mit unterschiedlichen Befehlssätzen genau gleich läuft, selbst wenn unterschiedliche Betriebssysteme ausgeführt werden. Es gab jedoch ein Problem mit Dezimalstellen, die in Programmiersprachen auch als Gleitkomma- und Doppelpunktzahlen bezeichnet werden. Einige Maschinen wurden so gebaut, dass sie auf Effizienz abzielen, während der Rest auf Genauigkeit abzielte. Die späteren (genaueren) Maschinen hatten also eine Gleitkommagröße von 80 Bit, während die früheren (effizienteren / schnelleren) Maschinen 64-Bit-Doppel hatten. Dies widersprach jedoch der Kernidee, eine plattformunabhängige Sprache aufzubauen. Dies kann auch zu einem Verlust an Präzision / Daten führen, wenn ein Code auf einem Computer (mit einer doppelten Größe von 64 Bit) erstellt und auf einem anderen Maschinentyp (mit einer doppelten Größe von 80 Bit) ausgeführt wird.

Up-Sizing kann toleriert werden, Down-Sizing jedoch nicht. Sie stießen also auf ein Konzept von strictfp, dh striktem Gleitkomma . Wenn Sie dieses Schlüsselwort mit einer Klasse / Funktion verwenden, haben Gleitkomma und Double eine einheitliche Größe für jede Maschine. dh 32/64 -bit.

AbhimanyuAryan
quelle
8
strictfp wurde in Java 1.2 eingeführt. Dies war viel später als bei der Gestaltung der Eiche.
Thorbjørn Ravn Andersen
"Dezimalpunktzahlen, auch als Gleitkommazahlen bekannt" - Dezimalzahl bedeutet Basis 10 und hat nichts mit Gleitkommadarstellungen zu tun.
Aioobe
21

Hier sind einige Referenzen:

  • Verwenden von strictfp (JDC Tech Tip)
  • jGuru: Wofür ist der strictfp-Modifikator? Wann würde ich in Betracht ziehen, es zu verwenden?

    Grundsätzlich läuft alles darauf hinaus, ob es Ihnen wichtig ist, dass die Ergebnisse von Gleitkommaausdrücken in Ihrem Code schnell oder vorhersehbar sind. Wenn Sie beispielsweise die Antworten benötigen, die Ihr Code enthält und die Gleitkommawerte verwenden, um auf mehreren Plattformen konsistent zu sein, verwenden Sie strictfp.

  • strictfp - Java Glossar

    Gleitkomma-Hardware berechnet genauer und mit einem größeren Wertebereich, als es die Java-Spezifikation erfordert. Es wäre verwirrend, wenn einige Plattformen präziser wären als andere. Wenn Sie den strictfpModifikator für eine Methode oder Klasse verwenden, generiert der Compiler Code, der sich strikt an die Java-Spezifikation hält, um auf allen Plattformen identische Ergebnisse zu erzielen. Ohne strictfpist es etwas lockerer, aber nicht so locker, dass die Schutzbits im Pentium verwendet werden, um 80 Bit Präzision zu erzielen.

  • Und schließlich die eigentliche Java-Sprachspezifikation, §15.4 FP-strenge Ausdrücke :

    Innerhalb eines FP-strengen Ausdrucks müssen alle Zwischenwerte Elemente des Float-Wertesatzes oder des Doppelwertsatzes sein, was bedeutet, dass die Ergebnisse aller FP-strengen Ausdrücke diejenigen sein müssen, die von der IEEE 754-Arithmetik für Operanden vorhergesagt werden, die im Einzel- und Doppelformat dargestellt werden . Innerhalb eines Ausdrucks, der nicht FP-streng ist, wird einer Implementierung ein gewisser Spielraum eingeräumt, um einen erweiterten Exponentenbereich zur Darstellung von Zwischenergebnissen zu verwenden. Der Nettoeffekt besteht grob gesagt darin, dass eine Berechnung in Situationen, in denen die ausschließliche Verwendung des Float-Wertesatzes oder des Doppelwertsatzes zu einem Über- oder Unterlauf führen kann, "die richtige Antwort" liefern kann.

Ich persönlich hatte jedoch nie eine Verwendung dafür.

Michael Myers
quelle
12

Wie in den anderen Antworten erwähnt, entsprechen die Zwischenergebnisse des Gleitkommas der IEEE-Spezifikation. Insbesondere x86-Prozessoren können Zwischenergebnisse mit einer anderen Genauigkeit als in der IEEE-Spezifikation speichern. Die Situation wird komplizierter, wenn die JIT eine bestimmte Berechnung optimiert. Die Reihenfolge der Anweisungen kann jedes Mal anders sein, was zu leicht unterschiedlichen Rundungen führt.

Der Overhead von strictfp ist wahrscheinlich sehr prozessor- und JIT-abhängig. Dieser Wikipedia-Artikel über SSE2 scheint einen Einblick in das Problem zu haben. Wenn die JIT also SSE-Anweisungen zur Durchführung einer Berechnung generieren kann, scheint strictfp keinen Overhead zu haben.

In meinem aktuellen Projekt gibt es einige Stellen, an denen ich strictfp verwende. Es gibt einen Punkt, an dem potenzielle kosmische Strahlen aus den Pixelwerten entfernt werden müssen. Wenn ein externer Forscher den gleichen Pixelwert und die gleiche kosmische Strahlung vor sich hat, sollte er den gleichen resultierenden Wert wie unsere Software erhalten.

Sean McCauliff
quelle
8
  • strictfp ist ein Modifikator, der Gleitkommaberechnungen gemäß IEEE 754 einschränkt.

  • Dies kann für eine ganze Klasse wie "public strictfp class StrictFpModifierExample {}" oder für die Methode "public strictfp void example ()" verwendet werden. Wenn es für eine Klasse verwendet wird, folgen alle Methoden IEEE 754, und wenn es für eine Methode verwendet wird, wird eine bestimmte Methode verwendet Folgen Sie IEEE 754.

  • Warum wird es verwendet? ::: Da verschiedene Plattformen unterschiedliche Gleitkomma-Hardware haben, die präziser und in einem größeren Wertebereich berechnet, als es die Java-Spezifikation erfordert, kann dies zu einer unterschiedlichen Ausgabe auf unterschiedlichen Plattenformen führen. Daher wird dieselbe Ausgabe unabhängig von der unterschiedlichen bestätigt Plattenformen

  • strictfp stellt außerdem sicher, dass die Geschwindigkeit und Präzision der Gleitkommaoperationen mit erweiterter Präzision genutzt werden.

  • Dieses Schlüsselwort, das wir bei Gleitkommaberechnungen verwenden können, hat keinen Nachteil

  • Mein letzter Punkt ist - Was ist IEEE754, kurz IEEE 754 definiert die Standardmethode sowohl für Gleitkommaberechnungen als auch für die Speicherung von Gleitkommawerten in Einzel- (32-Bit, in Java-Floats verwendet) oder Doppel- (64-Bit, in Java verwendet) Doppelte) Genauigkeit. Es definiert auch Normen für Zwischenberechnungen und für erweiterte Präzisionsformate.

Rahul Saxena
quelle
2

strictfpist ein Schlüsselwort und kann als Nicht-Zugriffsmodifikator für Klassen oder Methoden (jedoch niemals Variablen) verwendet werden. Das Markieren einer Klasse als strictfpbedeutet, dass jeder Methodencode in der Klasse den IEEE 754-Standardregeln für Gleitkommazahlen entspricht.

Ohne diesen Modifikator können sich Gleitkommawerte, die in den Methoden verwendet werden, plattformabhängig verhalten. Damit können Sie vorhersagen, wie sich Ihre Gleitkommawerte unabhängig von der zugrunde liegenden Plattform, auf der die JVM ausgeführt wird, verhalten werden. Der Nachteil ist, dass eine strictfpMethode diese nicht nutzen kann , wenn die zugrunde liegende Plattform eine höhere Präzision unterstützt .

Wenn Sie eine Klasse nicht als deklarieren strictfp, können Sie das strictfpVerhalten immer noch methodenweise abrufen, indem Sie eine Methode als deklarieren strictfp.

~ SCJP Sun®Certified Programmer für Java ™ 6 - Kathy Sierra & Bert Bates ~

Shanaka Jayalath
quelle
0

Kann das folgende Beispiel helfen, dies klarer zu verstehen: In Java, wenn wir nach genauen Informationen für eine Operation suchen, z. B. wenn wir double num1 = 10e + 102 ausführen; doppelte Zahl2 = 8e + 10; Ergebnis = num1 + num2;

        The output will be so long and not precise, becasue it is precissed by the hardware e.g JVM and JIT has the license 
        as long as we dont have specify it Strictfp

Marking it Strictfp will make the result Uniform on every hardware and platform, because its precised value will be same
One scenario I can see is in a distributed application (or multiplayer game) where all floating-point calculations need to 
be deterministic no matter what the underlying hardware or CPU is.
Neeraj
quelle
0

Das Schlüsselwort 'strictfp' wird verwendet, um die Genauigkeit von Gleitkommaberechnungen (float oder double) in Java zu erzwingen, die explizit dem IEEE-Standard 754 entsprechen. Wenn Sie das Schlüsselwort strictfp nicht verwenden, hängt die Gleitkommapräzision von der Hardware der Zielplattform ab.

Wenn eine Schnittstelle oder Klasse mit strictfp deklariert wird, sind alle Methoden und verschachtelten Typen innerhalb dieser Schnittstelle oder Klasse implizit strictfp.

Referenz - Link

Hari Krishna
quelle