Quando dovrei usare la parola chiave "strictfp" in Java?


258

Ho cercato cosa fa, ma qualcuno ha effettivamente un esempio di quando useresti la strictfpparola chiave in Java? Qualcuno ha effettivamente trovato un uso per questo?

Ci sarebbero effetti collaterali nel metterlo su tutte le mie operazioni in virgola mobile?


1
Sempre, a meno che tu non abbia effettivamente bisogno delle prestazioni più di quanto tu abbia bisogno di riproducibilità.
Antimonio

1
@Antimonio - o la precisione / correttezza. x86 / x64, ad esempio, utilizza internamente registri a virgola mobile a 80 bit, quindi il risultato sarà più accurato per un lungo calcolo senza strictfp.
Robert Fraser,

1
@Robert In realtà, le specifiche garantiscono una precisione limitata della mantissa. L'unica differenza è che può usare una precisione esponente maggiore del normale, che ha differenze in rari casi a causa del doppio arrotondamento.
Antimonio

Sto pensando che oltre all'opzione di cospargere questo utile modificatore in tutto il giunto, i nuovi tipi di dati sfloat e sdouble primitivi strictfp potrebbero essere una buona idea.
theRiley il

Risposte:


274

Strictfp ti assicura di ottenere esattamente gli stessi risultati dai calcoli in virgola mobile su ogni piattaforma. Se non si utilizza strictfp, l'implementazione di JVM è libera di utilizzare una precisione aggiuntiva ove disponibile.

Dal JLS :

All'interno di un'espressione rigorosa FP, tutti i valori intermedi devono essere elementi dell'insieme di valori float o dell'insieme doppio valore, il che implica che i risultati di tutte le espressioni rigorose FP devono essere quelli previsti dall'aritmetica IEEE 754 sugli operandi rappresentati utilizzando formati singoli e doppi . All'interno di un'espressione non rigorosa in termini di FP, viene concesso un margine di manovra affinché un'implementazione utilizzi un intervallo esponente esteso per rappresentare risultati intermedi; l'effetto netto, in termini approssimativi, è che un calcolo potrebbe produrre "la risposta corretta" in situazioni in cui l'uso esclusivo del set di valori float o doppio set di valori potrebbe provocare overflow o underflow.

In altre parole, si tratta di assicurarsi che Write-Once-Run-Anywhere significhi effettivamente Write-Once-Get-Equally-Wrong-Results-Everywhere .

Con strictfp i risultati sono portatili, senza di essi è più probabile che siano precisi.


28
Usalo per risultati scientifici riproducibili e test unitari esatti.
Aleksandr Dubinsky,

1
"Se non si usa strictfp, l'implementazione di JVM è libera di usare una precisione extra laddove disponibile" - si fa sembrare una cosa negativa: P
AMDG

@LinkTheProgrammer può certamente essere una brutta cosa
Tim

@TimCastelijns Suppongo che Happy Wheels sia il tuo riferimento? I replay registrano i tasti premuti; a causa della diversità di precisione dell'implementazione di FP-math, i replay sono accurati solo su hardware simile. Puoi nominare un problema più realistico causato dalla variabilità matematica in virgola mobile? Posso immaginare forse un simulatore di particelle, ma cos'altro?
AMDG,

Quindi questo significa che dovremmo sempre usare strictfp nella produzione in cui sono coinvolte più piattaforme?
Beatrice,

65

Wikipedia in realtà ha un buon articolo su questo argomento qui , con un link alla specifica Java.

Leggendo tra le righe, l'implicazione è che se non si specifica strictfp, quindi il compilatore JVM e JIT hanno la licenza per calcolare i calcoli in virgola mobile come vogliono. Nell'interesse della velocità, molto probabilmente delegheranno il calcolo al tuo processore. Con strictfpon, i calcoli devono essere conformi agli standard aritmetici IEEE 754, che, in pratica, probabilmente significa che la JVM eseguirà il calcolo.

Quindi perché dovresti usare strictfp? Uno scenario che posso vedere è in un'applicazione distribuita (o gioco multiplayer) in cui tutti i calcoli in virgola mobile devono essere deterministici, indipendentemente dall'hardware o dalla CPU sottostanti. Qual è il compromesso? Molto probabilmente il tempo di esecuzione.


5
"Una gamma estesa di esponenti per rappresentare risultati intermedi" non è "la licenza per calcolare i calcoli in virgola mobile come vogliono" e, in pratica, anche i strictfpcalcoli fanno uso anche di una FPU 8087 inutile. Solo allora è necessario un po 'di cura. Vedi stackoverflow.com/questions/18496560/…
Pascal Cuoq

Sono d'accordo con @PascalCuoq re: "licenza per calcolare i calcoli in virgola mobile come vogliono" . Semmai, il contrario sembra essere vero in questo caso, poiché strictfpassicura la conformità allo standard IEEE 754 (in modo da ottenere lo stesso risultato su tutte le piattaforme). L'unico inconveniente che posso vedere è che potresti perdere i vantaggi di avere una FPU davvero buona disponibile nel tuo hardware nativo.
Typeracer,

25

Tutto è iniziato con una storia,

Quando Java era sviluppato da James Gosling, Herbert e il resto del suo team. Avevano in mente questa cosa folle chiamata indipendenza dalla piattaforma . Volevano fare la quercia (Java)molto meglio che funzionerebbe esattamente allo stesso modo su qualsiasi macchina con set di istruzioni diverso, anche con sistemi operativi diversi. Ma c'era un problema con i numeri decimali noti anche come virgola mobile e doppio nei linguaggi di programmazione. Alcune macchine sono state costruite mirando all'efficienza mentre il resto mirava alla precisione. Quindi, le macchine successive (più accurate) avevano una dimensione in virgola mobile di 80 bit mentre le macchine precedenti (più efficienti / più veloci) avevano raddoppia a 64 bit. Ma questo era contro l'idea centrale di costruire un linguaggio indipendente dalla piattaforma. Inoltre, ciò potrebbe comportare la perdita di precisione / dati quando un codice viene creato su una macchina (con dimensioni doppie di 64 bit) ed eseguito su un altro tipo di macchina (con dimensioni doppie di 80 bit).

Il ridimensionamento può essere tollerato, ma il ridimensionamento non può essere. Così, si sono imbattuti in un concetto di strictfp, ovvero in virgola mobile rigorosa . Se usi questa parola chiave con una classe / funzione, il suo punto in virgola mobile e i suoi doppi hanno una dimensione coerente su qualsiasi macchina. cioè 32/64 bit rispettivamente.


8
strictfp è stato introdotto in Java 1.2. Questo è stato molto più tardi rispetto a quando è stata progettata la quercia.
Thorbjørn Ravn Andersen,

"numeri decimali noti anche come virgola mobile": i decimali indicano la base 10 e non hanno nulla a che fare con le rappresentazioni in virgola mobile.
aioobe,

21

Ecco alcuni riferimenti:

  • Utilizzo di strictfp (JDC Tech Tip)
  • jGuru: A cosa serve il modificatore strictfp? Quando dovrei considerare di usarlo?

    Fondamentalmente, ciò a cui tutto si riduce è se ti interessa o meno che i risultati delle espressioni in virgola mobile nel tuo codice siano veloci o prevedibili. Ad esempio, se hai bisogno delle risposte fornite dal tuo codice che utilizza valori in virgola mobile per essere coerenti su più piattaforme, utilizza strictfp.

  • strictfp - Glossario Java

    L'hardware in virgola mobile calcola con maggiore precisione e con un intervallo di valori maggiore rispetto alle specifiche Java richieste. Sarebbe confuso se alcune piattaforme offrissero più precisione di altre. Quando si utilizza il strictfpmodificatore su un metodo o una classe, il compilatore genera codice che aderisce rigorosamente alle specifiche Java per risultati identici su tutte le piattaforme. Senza strictfp, è leggermente più rilassato, ma non così rilassato da usare i bit di protezione nel Pentium per dare 80 bit di precisione.

  • E infine l'attuale specifica del linguaggio Java, §15.4 FP-rigorose espressioni :

    All'interno di un'espressione rigorosa FP, tutti i valori intermedi devono essere elementi dell'insieme di valori float o dell'insieme doppio valore, il che implica che i risultati di tutte le espressioni rigorose FP devono essere quelli previsti dall'aritmetica IEEE 754 sugli operandi rappresentati utilizzando formati singoli e doppi . All'interno di un'espressione non rigorosa in termini di FP, viene concesso un margine di manovra affinché un'implementazione utilizzi un intervallo esponente esteso per rappresentare risultati intermedi; l'effetto netto, in termini approssimativi, è che un calcolo potrebbe produrre "la risposta corretta" in situazioni in cui l'uso esclusivo del set di valori float o doppio set di valori potrebbe provocare overflow o underflow.

Non ne ho mai avuto personalmente uso, però.


12

Come indicato nelle altre risposte, i risultati in virgola mobile intermedi sono conformi alle specifiche IEEE. In particolare i processori x86 possono archiviare risultati intermedi con precisione diversa dalle specifiche IEEE. La situazione diventa più complicata quando la SIC ottimizza un calcolo particolare; l'ordine delle istruzioni potrebbe essere diverso ogni volta con conseguente arrotondamento leggermente diverso.

Le spese generali sostenute da strictfp probabilmente dipenderanno molto dal processore e dal JIT. Questo articolo di Wikipedia su SSE2 sembra avere qualche idea sul problema. Quindi, se la JIT è in grado di generare istruzioni SSE per eseguire un calcolo, sembra che strictfp non avrà alcun sovraccarico.

Nel mio progetto attuale ci sono alcuni posti in cui uso strictfp. C'è un punto in cui i potenziali raggi cosmici devono essere rimossi dai valori dei pixel. Se alcuni ricercatori esterni hanno lo stesso valore di pixel e raggio cosmico di fronte a loro, dovrebbero ottenere lo stesso valore risultante del nostro software.


8
  • strictfp è un modificatore che limita i calcoli in virgola mobile secondo IEEE 754.

  • Questo può essere usato su tutta la classe come "public strictfp class StrictFpModifierExample {}" o sul metodo "public strictfp void example ()". Se viene usato su class, tutti i metodi seguiranno IEEE 754 e se usato su method, allora un metodo particolare seguire IEEE 754.

  • Perché viene utilizzato ?? ::: Poiché piattaforme diverse hanno hardware a virgola mobile diverso che calcola con maggiore precisione e un intervallo di valori maggiore rispetto alle specifiche java richieste che possono produrre output diversi su forme di lastre diverse, quindi conferma lo stesso output indipendentemente dal diverso plateforms

  • strictfp garantisce inoltre di sfruttare la velocità e la precisione delle operazioni in virgola mobile di precisione estesa.

  • Non ci sono svantaggi con questa parola chiave che possiamo usare quando eseguiamo calcoli in virgola mobile

  • Il mio ultimo punto è: che cos'è IEEE754 in breve IEEE 754 definisce il metodo standard sia per i calcoli in virgola mobile sia per l'archiviazione di valori in virgola mobile in singolo (32 bit, utilizzato in float Java) o doppio (64 bit, utilizzato in Java raddoppia) precisione. Definisce inoltre le norme per i calcoli intermedi e per i formati di precisione estesi.


2

strictfpè una parola chiave e può essere utilizzata come modificatore di non accesso per classi o metodi (ma mai variabili). Contrassegnare una classe come strictfpsignifica che qualsiasi codice di metodo nella classe sarà conforme alle regole standard IEEE 754 per i punti mobili.

Senza quel modificatore, i punti mobili utilizzati nei metodi potrebbero comportarsi in modo dipendente dalla piattaforma. Con esso puoi prevedere come si comporteranno i tuoi punti mobili indipendentemente dalla piattaforma sottostante su cui è in esecuzione JVM. Il rovescio della medaglia è che se la piattaforma sottostante è in grado di supportare una maggiore precisione, un strictfpmetodo non sarà in grado di trarne vantaggio.

Se non si dichiara una classe come strictfp, è comunque possibile ottenere un strictfpcomportamento metodo per metodo, dichiarando un metodo come strictfp.

~ Programmatore certificato SCJP Sun® per Java ™ 6 - Kathy Sierra e Bert Bates ~


0

Può essere utile sotto l'esempio per capire meglio questo: in java ogni volta che stiamo cercando informazioni precise per qualsiasi operazione, ad esempio se facciamo doppio num1 = 10e + 102; doppio num2 = 8e + 10; risultato = 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.

0

La parola chiave 'strictfp' viene utilizzata per forzare la precisione dei calcoli in virgola mobile (float o double) in Java conforme allo standard IEEE 754, esplicitamente. Se non si utilizza la parola chiave strictfp, la precisione in virgola mobile dipende dall'hardware della piattaforma di destinazione.

Se un'interfaccia o una classe viene dichiarata con strictfp, tutti i metodi e tipi nidificati all'interno di tale interfaccia o classe sono implicitamente rigorfp.

Link di riferimento

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.