Kiedy powinienem używać słowa kluczowego „strictfp” w java?


258

Sprawdziłem, co to robi, ale czy ktoś rzeczywiście ma przykład, kiedy użyjesz strictfpsłowa kluczowego w Javie? Czy ktoś znalazł zastosowanie do tego?

Czy byłyby jakieś skutki uboczne po prostu nałożenie go na wszystkie operacje zmiennoprzecinkowe?


1
Zawsze, chyba że faktycznie potrzebujesz wydajności bardziej niż potrzebujesz odtwarzalności.
Antymon

1
@Antimony - lub precyzja / poprawność. Na przykład x86 / x64 używają 80-bitowych rejestrów zmiennoprzecinkowych wewnętrznie, więc wynik będzie dokładniejszy w przypadku długich obliczeń bez ścisłej dokładności.
Robert Fraser,

1
@Robert Właściwie specyfikacja gwarantuje ograniczoną precyzję mantysy. Jedyną różnicą jest to, że może używać większej wykładniczej precyzji niż zwykle, co w rzadkich przypadkach różni się z powodu podwójnego zaokrąglenia.
Antymon

Myślę, że oprócz opcji rozsypywania tego użytecznego modyfikatora wokół połączenia, dobrym rozwiązaniem mogą być nowe prymitywne typy danych sfloat i sdouble prymitywne strictfp.
theRiley

Odpowiedzi:


274

Strictfp zapewnia, że ​​otrzymujesz dokładnie takie same wyniki z obliczeń zmiennoprzecinkowych na każdej platformie. Jeśli nie używasz strictfp, implementacja JVM może używać dodatkowej precyzji, jeśli jest dostępna.

Z JLS :

W wyrażeniu ścisłym FP wszystkie wartości pośrednie muszą być elementami zestawu wartości zmiennoprzecinkowych lub zestawu podwójnych wartości, co oznacza, że ​​wyniki wszystkich wyrażeń ścisłych FP muszą być tymi przewidywanymi przez arytmetykę IEEE 754 na operandach reprezentowanych przy użyciu formatów pojedynczego i podwójnego . W ramach wyrażenia, które nie jest ściśle związane z FP, pewna swoboda daje implementacji możliwość użycia rozszerzonego zakresu wykładników do przedstawienia wyników pośrednich; z grubsza efekt netto jest taki, że obliczenia mogą dać „poprawną odpowiedź” w sytuacjach, w których wyłączne użycie zestawu wartości zmiennoprzecinkowych lub zestawu podwójnych wartości może spowodować przepełnienie lub niedopełnienie.

Innymi słowy, chodzi o to, aby upewnić się, że Write-Once-Run-Anywhere faktycznie oznacza Write-Once-Get-Equally-Wrong-Results-Everywhere .

Dzięki strictfp twoje wyniki są przenośne, bez tego bardziej prawdopodobne jest, że będą dokładne.


28
Użyj go do powtarzalnych wyników naukowych i dokładnych testów jednostkowych.
Aleksandr Dubinsky

1
„Jeśli nie używasz strictfp, implementacja JVM może używać dodatkowej precyzji, o ile jest dostępna” - brzmi to źle: P
AMDG

@LinkTheProgrammer to z pewnością może być zła rzecz
Tim

@TimCastelijns Podejrzewam, że Happy Wheels jest Twoim odniesieniem? Powtórki rejestrują naciśnięcia klawiszy; ze względu na różnorodność precyzji implementacji matematyki, powtórzenia są dokładne tylko na podobnym sprzęcie. Czy możesz wymienić bardziej realistyczny problem spowodowany zmiennością matematyczną zmiennoprzecinkową? Mogę sobie wyobrazić symulator cząstek, ale co jeszcze?
AMDG

Oznacza to, że zawsze powinniśmy używać strictfp w produkcji, w której bierze udział wiele platform?
beatrice

65

Wikipedia faktycznie ma dobry artykuł na ten temat tutaj , z linkiem do specyfikacji Java.

Czytanie między wierszami implikuje, że jeśli nie określisz strictfp, to JVM i kompilator JIT mają licencję na obliczanie obliczeń zmiennoprzecinkowych w dowolny sposób. Ze względu na szybkość najprawdopodobniej przekażą obliczenia procesorowi. Po strictfpwłączeniu obliczenia muszą być zgodne ze standardami arytmetycznymi IEEE 754, co w praktyce prawdopodobnie oznacza, że ​​JVM wykona obliczenia.

Dlaczego więc chcesz użyć strictfp? Jeden ze scenariuszy, jaki widzę, dotyczy aplikacji rozproszonej (lub gry wieloosobowej), w której wszystkie obliczenia zmiennoprzecinkowe muszą być deterministyczne bez względu na to, jaki jest podstawowy sprzęt lub procesor. Jaki jest kompromis? Najprawdopodobniej czas wykonania.


5
„Rozszerzony zakres wykładników do reprezentowania wyników pośrednich” nie jest „licencją na obliczanie obliczeń zmiennoprzecinkowych, jak chcą”, aw praktyce nawet strictfpobliczenia wykorzystują nawet nieprzydatne 8087 FPU. Tylko wtedy wymagana jest ostrożność. Zobacz stackoverflow.com/questions/18496560/…
Pascal Cuoq

Zgadzam się z @PascalCuoq re: „licencja na obliczanie obliczeń zmiennoprzecinkowych w dowolny sposób” . W przeciwnym razie wydaje się, że w tym przypadku jest odwrotnie, ponieważ strictfpzapewnia zgodność ze standardem IEEE 754 (aby uzyskać taki sam wynik na wszystkich platformach). Jedyną wadą, jaką widzę, jest to, że możesz stracić korzyści z posiadania naprawdę dobrego FPU dostępnego na twoim rodzimym sprzęcie.
typeracer

25

Wszystko zaczęło się od historii

Kiedy James Gosling opracowywał Javę, Herbert i reszta jego zespołu. Mieli na myśli tę szaloną rzecz zwaną niezależnością od platformy . Chcieli zrobić dąb (Java)o wiele lepiej, że działałoby dokładnie tak samo na każdym komputerze z innym zestawem instrukcji, nawet działającym w różnych systemach operacyjnych. Wystąpił jednak problem z liczbami dziesiętnymi znanymi również jako zmiennoprzecinkowe i podwójne w językach programowania. Niektóre maszyny zostały zbudowane pod kątem wydajności celowania, podczas gdy reszta celowała w celność. Tak więc późniejsze (dokładniejsze) maszyny miały zmiennoprzecinkowe 80 bitów, podczas gdy poprzednie (bardziej wydajne / szybsze) miały 64-bitowe podwójne. Było to jednak sprzeczne z podstawową ideą budowy niezależnego od platformy języka. Może to również prowadzić do utraty precyzji / danych, gdy kod zostanie zbudowany na jakiejś maszynie (o podwójnym rozmiarze 64 bitów) i uruchomiony na innym rodzaju maszyny (o podwójnej wielkości 80 bitów).

Zwiększanie rozmiaru może być tolerowane, ale zmniejszanie rozmiaru nie może być. Tak więc natrafili na koncepcję strictfp, czyli ścisłego zmiennoprzecinkowego . Jeśli użyjesz tego słowa kluczowego z klasą / funkcją, wówczas liczba zmiennoprzecinkowa i liczba podwójna mają stały rozmiar na dowolnej maszynie. tj. odpowiednio 32/64-bit.


8
strictfp został wprowadzony w Javie 1.2. Było to znacznie później niż w momencie projektowania dębu.
Thorbjørn Ravn Andersen

„liczby dziesiętne znane również jako zmiennoprzecinkowe” - dziesiętny oznacza podstawę 10 i nie ma nic wspólnego z reprezentacjami zmiennoprzecinkowymi.
aioobe,

21

Oto kilka referencji:

  • Korzystanie z strictfp (Wskazówka techniczna JDC)
  • jGuru: Do czego służy modyfikator strictfp? Kiedy powinienem rozważyć jego użycie?

    Zasadniczo wszystko sprowadza się do tego, czy zależy Ci na tym, aby wyniki wyrażeń zmiennoprzecinkowych w kodzie były szybkie lub przewidywalne. Na przykład, jeśli potrzebujesz odpowiedzi, które pojawia się w kodzie, w których wartości zmiennoprzecinkowe są spójne na wielu platformach, użyj strictfp.

  • strictfp - Java Glossary

    Sprzęt zmiennoprzecinkowy oblicza z większą precyzją i przy większym zakresie wartości niż wymaga specyfikacja Java. Byłoby mylące, gdyby niektóre platformy dawały większą precyzję niż inne. Gdy używasz strictfpmodyfikatora w metodzie lub klasie, kompilator generuje kod ściśle zgodny ze specyfikacją Java, aby uzyskać identyczne wyniki na wszystkich platformach. Bez strictfpjest nieco luźniejszy, ale nie tak luźny, aby użyć bitów ochronnych w Pentium, aby uzyskać 80 bitów precyzji.

  • I wreszcie faktyczna specyfikacja języka Java, wyrażenia §15.4 FP :

    W wyrażeniu ścisłym FP wszystkie wartości pośrednie muszą być elementami zestawu wartości zmiennoprzecinkowych lub zestawu podwójnych wartości, co oznacza, że ​​wyniki wszystkich wyrażeń ścisłych FP muszą być tymi przewidywanymi przez arytmetykę IEEE 754 na operandach reprezentowanych przy użyciu formatów pojedynczego i podwójnego . W ramach wyrażenia, które nie jest ściśle związane z FP, pewna swoboda daje implementacji możliwość użycia rozszerzonego zakresu wykładników do przedstawienia wyników pośrednich; z grubsza efekt netto jest taki, że obliczenia mogą dać „poprawną odpowiedź” w sytuacjach, w których wyłączne użycie zestawu wartości zmiennoprzecinkowych lub zestawu podwójnych wartości może spowodować przepełnienie lub niedopełnienie.

Jednak nigdy osobiście nie miałem z tego pożytku.


12

Jak wspomniano w innych odpowiedziach, wyniki pośredniego zmiennoprzecinkowego są zgodne ze specyfikacją IEEE. W szczególności procesory x86 mogą przechowywać wyniki pośrednie z inną precyzją niż specyfikacja IEEE. Sytuacja komplikuje się, gdy JIT optymalizuje dane obliczenia; kolejność instrukcji może być za każdym razem inna, co skutkuje nieco innym zaokrągleniem.

Koszty ogólne poniesione przez strictfp prawdopodobnie będą bardzo zależne od procesora i JIT. Ten artykuł Wikipedii na temat SSE2 wydaje się mieć pewien wgląd w problem. Więc jeśli JIT może wygenerować instrukcje SSE do wykonania obliczeń, wydaje się, że strictfp nie będzie miał narzutu.

W moim obecnym projekcie jest kilka miejsc, w których używam strictfp. Istnieje punkt, w którym potencjalne promienie kosmiczne muszą zostać usunięte z wartości pikseli. Jeśli jakiś zewnętrzny badacz ma przed sobą tę samą wartość pikseli i promień kosmiczny, powinni otrzymać taką samą wartość wynikową jak nasze oprogramowanie.


8
  • strictfp to modyfikator, który ogranicza obliczenia zmiennoprzecinkowe zgodnie z IEEE 754.

  • Można tego użyć w całej klasie, takiej jak „public strictfp StrictFpModifierExample {}” lub w metodzie „public strictfp void example ()”. Jeśli zostanie użyty w klasie, wszystkie metody będą zgodne z IEEE 754, a jeśli zastosowane w metodzie, to określona metoda będzie postępuj zgodnie z IEEE 754.

  • Dlaczego jest używany? ::: Ponieważ różne platformy mają inny sprzęt zmiennoprzecinkowy, który oblicza z większą precyzją i większym zakresem wartości niż wymaga specyfikacja java, co może dawać różne dane wyjściowe na różnych formach płyt. Więc potwierdza to samo wyjście niezależnie od różnych formy płytowe

  • strictfp zapewnia także szybkość i precyzję operacji zmiennoprzecinkowych o rozszerzonej precyzji.

  • Nie ma wady tego słowa kluczowego, którego możemy użyć podczas wykonywania obliczeń zmiennoprzecinkowych

  • Mój ostatni punkt - Czym jest IEEE754 w skrócie IEEE 754 definiuje standardową metodę zarówno dla obliczeń zmiennoprzecinkowych, jak i przechowywania wartości zmiennoprzecinkowych w jednym (32-bitowym, używanym w pływakach Java) lub podwójnym (64-bitowym, używanym w Javie precyzja). Definiuje również normy dla obliczeń pośrednich i dla formatów o rozszerzonej precyzji.


2

strictfpjest słowem kluczowym i może być używany jako modyfikator braku dostępu do klas lub metod (ale nigdy zmiennych). Oznaczenie klasy jako strictfpoznacza, że ​​dowolny kod metody w klasie będzie zgodny ze standardowymi regułami IEEE 754 dla liczb zmiennoprzecinkowych.

Bez tego modyfikatora zmiennoprzecinkowe użyte w metodach mogą zachowywać się w sposób zależny od platformy. Dzięki niemu możesz przewidzieć, jak będą się zachowywać zmiennoprzecinkowe, niezależnie od platformy, na której działa JVM. Minusem jest to, że jeśli podstawowa platforma jest w stanie obsługiwać większą precyzję, strictfpmetoda nie będzie w stanie z niej skorzystać.

Jeśli nie zadeklarujesz klasy jako strictfp, nadal możesz uzyskać strictfpzachowanie metoda po metodzie, deklarując metodę jako strictfp.

~ SCJP Sun® Certyfikowany programista dla Java ™ 6 - Kathy Sierra i Bert Bates ~


0

Poniższy przykład może pomóc w lepszym zrozumieniu tego: w java, ilekroć używamy szukania dokładnych informacji dla dowolnej operacji, np. Jeśli wykonamy podwójne num1 = 10e + 102; podwójne num2 = 8e + 10; wynik = 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

Słowo kluczowe „strictfp” jest używane do wymuszenia jawnej precyzji obliczeń zmiennoprzecinkowych (zmiennoprzecinkowych lub podwójnych) w Javie zgodnie ze standardem IEEE 754. Jeśli nie użyjesz słowa kluczowego strictfp, precyzja zmiennoprzecinkowa zależy od sprzętu platformy docelowej.

Jeśli interfejs lub klasa jest zadeklarowana za pomocą strictfp, wówczas wszystkie metody i typy zagnieżdżone w tym interfejsie lub klasie są domyślnie strictfp.

Link referencyjny

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.