Khi nào tôi nên sử dụng từ khóa chặt chẽ của Wikipedia trong java?


258

Tôi đã tìm kiếm những gì nó làm, nhưng có ai thực sự có một ví dụ về khi bạn sẽ sử dụng strictfptừ khóa trong Java? Có ai thực sự tìm thấy một sử dụng cho điều này?

Sẽ có bất kỳ tác dụng phụ nào của việc đưa nó vào tất cả các hoạt động điểm nổi của tôi?


1
Luôn luôn, trừ khi bạn thực sự cần hiệu suất nhiều hơn bạn cần tái sản xuất.
Antimon

1
@Antimony - hoặc độ chính xác / chính xác. x86 / x64, ví dụ, sử dụng các thanh ghi dấu phẩy động 80 bit bên trong, do đó, kết quả sẽ chính xác hơn cho một phép tính dài mà không nghiêm ngặt.
Robert Fraser

1
@Robert Trên thực tế, thông số kỹ thuật đảm bảo độ chính xác hạn chế của lớp phủ. Sự khác biệt duy nhất là nó có thể sử dụng độ chính xác số mũ lớn hơn bình thường, có sự khác biệt trong các trường hợp hiếm do làm tròn số.
Antimon

Tôi nghĩ rằng ngoài tùy chọn rắc công cụ sửa đổi hữu ích này xung quanh khớp, các kiểu dữ liệu nghiêm ngặt nguyên thủy sfloat & sdouble mới có thể là một ý tưởng tốt.
theRiley

Câu trả lời:


274

Strictfp đảm bảo rằng bạn nhận được kết quả chính xác từ các phép tính dấu phẩy động trên mọi nền tảng. Nếu bạn không sử dụngrictfp, việc triển khai JVM hoàn toàn miễn phí khi sử dụng độ chính xác cao hơn nếu có.

Từ JLS :

Trong biểu thức nghiêm ngặt của FP, tất cả các giá trị trung gian phải là các phần tử của tập giá trị float hoặc tập giá trị kép, ngụ ý rằng kết quả của tất cả các biểu thức nghiêm ngặt của FP phải là các số liệu được dự đoán bởi số học của IEEE 754 trên các toán hạng được biểu diễn bằng các định dạng đơn và kép . Trong một biểu thức không nghiêm ngặt của FP, một số độ trễ được cấp cho việc triển khai sử dụng phạm vi số mũ mở rộng để biểu thị các kết quả trung gian; hiệu ứng ròng, nói một cách đại khái, là một phép tính có thể tạo ra "câu trả lời đúng" trong trường hợp sử dụng độc quyền bộ giá trị float hoặc bộ giá trị kép có thể dẫn đến tràn hoặc tràn.

Nói cách khác, đó là về việc đảm bảo rằng Viết-Một lần-Chạy-Bất cứ nơi nào thực sự có nghĩa là Viết-Một lần-Nhận-Bằng-Sai-Kết quả-Mọi nơi .

Với nghiêm ngặt, kết quả của bạn là di động, nếu không có nó, chúng có nhiều khả năng chính xác hơn.


28
Sử dụng nó cho các kết quả khoa học có thể tái tạo và các bài kiểm tra đơn vị chính xác bit.
Alexanderr Dubinsky

1
"Nếu bạn không sử dụngrictfp, việc triển khai JVM hoàn toàn miễn phí khi sử dụng độ chính xác cao hơn nếu có" - bạn làm cho âm thanh đó giống như một điều tồi tệ: P
AMDG

@LinkTheProgrammer nó chắc chắn có thể là một điều xấu
Tim

@TimCastelijns Tôi cho rằng Happy Wheels là tài liệu tham khảo của bạn? Các replay ghi lại tổ hợp phím; do tính đa dạng chính xác của triển khai toán học FP, các replay chỉ chính xác trên phần cứng tương tự. Bạn có thể đặt tên cho một vấn đề thực tế hơn gây ra bởi biến thiên toán học dấu phẩy động? Tôi có thể tưởng tượng có lẽ là một mô phỏng hạt, nhưng những gì khác?
AMDG

Vì vậy, điều này có nghĩa là chúng ta nên luôn luôn sử dụngrictfp trong sản xuất, nơi có nhiều nền tảng tham gia?
beatrice

65

Wikipedia thực sự có một bài viết hay về chủ đề này ở đây , với một liên kết đến đặc tả Java.

Đọc giữa các dòng, hàm ý là nếu bạn không chỉ định strictfp, thì trình biên dịch JVM và JIT có giấy phép để tính toán các phép tính dấu phẩy động của bạn theo cách họ muốn. Vì lợi ích của tốc độ, rất có thể họ sẽ ủy thác việc tính toán cho bộ xử lý của bạn. Với strictfp, các tính toán phải tuân theo các tiêu chuẩn số học của IEEE 754, trong thực tế, có lẽ có nghĩa là JVM sẽ thực hiện tính toán.

Vậy tại sao bạn muốn sử dụng strictfp? Một kịch bản tôi có thể thấy là trong một ứng dụng phân tán (hoặc trò chơi nhiều người chơi) trong đó tất cả các phép tính dấu phẩy động cần phải có tính xác định cho dù phần cứng hay CPU cơ bản là gì. Sự đánh đổi là gì? Nhiều khả năng thời gian thực hiện.


5
Một phạm vi số mũ mở rộng để biểu thị các kết quả trung gian strictfp. Nó chỉ là trường hợp một chút chăm sóc được yêu cầu sau đó. Xem stackoverflow.com/questions/18496560/ Lời
Pascal Cuoq

Tôi đồng ý với @PascalCuoq re: "giấy phép tính toán các dấu phẩy động của bạn theo cách họ muốn" . Nếu bất cứ điều gì, điều ngược lại dường như là đúng trong trường hợp này, vì strictfpđảm bảo tuân thủ tiêu chuẩn IEEE 754 (để bạn có được kết quả tương tự trên tất cả các nền tảng). Hạn chế duy nhất tôi có thể thấy là bạn có thể mất những lợi ích của việc có sẵn một FPU thực sự tốt trong phần cứng tự nhiên của bạn.
typeracer

25

Tất cả bắt đầu với một câu chuyện,

Khi java được phát triển bởi James Gosling, Herbert và phần còn lại của nhóm. Họ có một thứ điên rồ trong tâm trí gọi là độc lập nền tảng . Họ muốn làm gỗ sồi (Java)tốt hơn nhiều đến mức nó sẽ chạy chính xác như nhau trên bất kỳ máy nào có tập lệnh khác nhau, thậm chí chạy các hệ điều hành khác nhau. Nhưng, có một vấn đề với số thập phân còn được gọi là dấu phẩy động và gấp đôi trong các ngôn ngữ lập trình. Một số máy được xây dựng hiệu quả nhắm mục tiêu trong khi phần còn lại nhắm mục tiêu chính xác. Vì vậy, các máy sau này (chính xác hơn) có kích thước điểm nổi là 80 bit trong khi các máy trước đây (hiệu quả hơn / nhanh hơn) có gấp đôi 64 bit. Nhưng, điều này đã chống lại ý tưởng cốt lõi là xây dựng một ngôn ngữ độc lập nền tảng. Ngoài ra, điều này có thể dẫn đến mất độ chính xác / dữ liệu khi mã được xây dựng trên một số máy (có kích thước gấp đôi 64 bit) và chạy trên một loại máy khác (có kích thước gấp đôi 80 bit).

Kích thước tăng có thể được chấp nhận nhưng kích thước xuống không thể. Vì vậy, họ đã bắt gặp một khái niệm về Severfp tức là điểm nổi nghiêm ngặt . Nếu bạn sử dụng từ khóa này với một lớp / hàm thì điểm nổi và nhân đôi của nó có kích thước phù hợp so với bất kỳ máy nào. tức là 32/64 -bit tương ứng.


8
rictfp đã được giới thiệu trong Java 1.2. Điều này đã muộn hơn nhiều so với khi gỗ sồi được thiết kế.
Thorbjørn Ravn Andersen

"Số thập phân còn được gọi là dấu phẩy động" - Số thập phân có nghĩa là cơ sở 10 và không liên quan gì đến các biểu diễn dấu phẩy động.
aioobe

21

Dưới đây là một số tài liệu tham khảo:

  • Sử dụngrictfp (Mẹo công nghệ JDC)
  • jGuru: Công cụ sửa đổi rictfp dùng để làm gì? Khi nào tôi sẽ xem xét sử dụng nó?

    Về cơ bản, tất cả những gì nó rút ra là liệu bạn có quan tâm rằng kết quả của các biểu thức dấu phẩy động trong mã của bạn là nhanh hay có thể dự đoán được hay không. Ví dụ: nếu bạn cần câu trả lời mà mã của bạn đưa ra, sử dụng các giá trị dấu phẩy động để thống nhất trên nhiều nền tảng thì hãy sử dụng strictfp.

  • rictfp - Thuật ngữ Java

    Phần cứng dấu phẩy động tính toán với độ chính xác cao hơn và với phạm vi giá trị lớn hơn so với đặc tả Java yêu cầu. Sẽ thật khó hiểu nếu một số nền tảng cho độ chính xác cao hơn những nền tảng khác. Khi bạn sử dụng công cụ strictfpsửa đổi trên một phương thức hoặc lớp, trình biên dịch sẽ tạo mã tuân thủ nghiêm ngặt thông số kỹ thuật Java để có kết quả giống hệt nhau trên tất cả các nền tảng. Không strictfp, nó hơi lỏng lẻo, nhưng không lỏng lẻo đến mức sử dụng các bit bảo vệ trong Pentium để cho độ chính xác 80 bit.

  • Và cuối cùng là Đặc tả ngôn ngữ Java thực tế, §15.4 Biểu thức nghiêm ngặt của FP :

    Trong biểu thức nghiêm ngặt của FP, tất cả các giá trị trung gian phải là các phần tử của tập giá trị float hoặc tập giá trị kép, ngụ ý rằng kết quả của tất cả các biểu thức nghiêm ngặt của FP phải là các số liệu được dự đoán bởi số học của IEEE 754 trên các toán hạng được biểu diễn bằng các định dạng đơn và kép . Trong một biểu thức không nghiêm ngặt của FP, một số độ trễ được cấp cho việc triển khai sử dụng phạm vi số mũ mở rộng để biểu thị các kết quả trung gian; hiệu ứng ròng, nói một cách đại khái, là một phép tính có thể tạo ra "câu trả lời đúng" trong trường hợp sử dụng độc quyền bộ giá trị float hoặc bộ giá trị kép có thể dẫn đến tràn hoặc tràn.

Tôi chưa bao giờ sử dụng cá nhân cho nó, mặc dù.


12

Như các câu trả lời khác đã đề cập, nó làm cho các kết quả dấu phẩy động trung gian phù hợp với đặc điểm kỹ thuật của IEEE. Cụ thể, bộ xử lý x86 có thể lưu trữ các kết quả trung gian với độ chính xác khác với thông số kỹ thuật của IEEE. Tình hình trở nên phức tạp hơn khi JIT tối ưu hóa một tính toán cụ thể; thứ tự các hướng dẫn có thể khác nhau mỗi lần dẫn đến làm tròn hơi khác nhau.

Chi phí phát sinh dorictfp có khả năng phụ thuộc rất nhiều vào bộ xử lý và JIT. Bài viết trên wikipedia về SSE2 này dường như có một số hiểu biết sâu sắc về vấn đề này. Vì vậy, nếu JIT có thể tạo các hướng dẫn SSE để thực hiện tính toán, có vẻ nhưrictfp sẽ không có bất kỳ chi phí nào.

Trong dự án hiện tại của tôi có một vài nơi tôi sử dụngrictfp. Có một điểm mà các tia vũ trụ tiềm năng cần phải được loại bỏ khỏi các giá trị pixel. Nếu một số nhà nghiên cứu bên ngoài có cùng giá trị pixel và tia vũ trụ ở phía trước thì họ sẽ nhận được giá trị kết quả tương tự như phần mềm của chúng tôi.


8
  • rictfp là một công cụ sửa đổi giới hạn các phép tính dấu phẩy động theo tiêu chuẩn IEEE 754.

  • Điều này có thể được sử dụng trên cả lớp như "lớprictfp công khai StrictFpModifierExample {}" hoặc trên phương thức "publicrictfp void example ()". Nếu nó được sử dụng trên lớp hơn tất cả các phương thức sẽ theo phương thức IEEE 754 và nếu được sử dụng trên phương thức thì phương thức cụ thể sẽ theo IEEE 754.

  • Tại sao nó được sử dụng ?? ::: Vì các nền tảng khác nhau có phần cứng dấu phẩy động khác nhau, tính toán với độ chính xác và phạm vi giá trị lớn hơn so với thông số java yêu cầu có thể tạo ra đầu ra khác nhau trên các dạng tấm khác nhau. Vì vậy, nó xác nhận cùng một đầu ra không phân biệt tấm

  • rictfp cũng đảm bảo tận dụng tốc độ và độ chính xác của các hoạt động điểm nổi chính xác mở rộng.

  • Không có bất lợi nào với từ khóa này, chúng ta có thể sử dụng khi thực hiện các phép tính dấu phẩy động

  • Điểm cuối cùng của tôi là - IEEE754 trong ngắn gọn là gì, IEEE 754 định nghĩa phương thức chuẩn cho cả tính toán dấu phẩy động và lưu trữ các giá trị dấu phẩy động ở dạng đơn (32 bit, được sử dụng trong phao Java) hoặc gấp đôi (64 bit, được sử dụng trong Java nhân đôi) độ chính xác. Nó cũng xác định định mức cho các tính toán trung gian và cho các định dạng chính xác mở rộng.


2

strictfplà một từ khóa và có thể được sử dụng như một công cụ sửa đổi không truy cập cho các lớp hoặc một phương thức (nhưng không bao giờ biến). Đánh dấu một lớp là strictfpcó nghĩa là bất kỳ mã phương thức nào trong lớp sẽ tuân thủ các quy tắc chuẩn của IEEE 754 cho các dấu phẩy động.

Không có công cụ sửa đổi đó, các điểm nổi được sử dụng trong các phương thức có thể hoạt động theo cách phụ thuộc vào nền tảng. Với nó, bạn có thể dự đoán các điểm nổi của bạn sẽ hoạt động như thế nào bất kể nền tảng cơ bản mà JVM đang chạy. Nhược điểm là nếu nền tảng cơ bản có khả năng hỗ trợ độ chính xác cao hơn, một strictfpphương pháp sẽ không thể tận dụng lợi thế của nó.

Nếu bạn không khai báo một lớp là strictfp, bạn vẫn có thể có strictfphành vi trên cơ sở từng phương thức, bằng cách khai báo một phương thức là strictfp.

~ SCJP Sun® Lập trình viên được chứng nhận cho Java ™ 6 - Kathy Sierra & Bert Bates ~


0

Ví dụ dưới đây có thể giúp hiểu rõ hơn về điều này: Trong java bất cứ khi nào chúng tôi đang sử dụng tìm kiếm thông tin chính xác cho bất kỳ hoạt động nào, ví dụ: nếu chúng tôi thực hiện gấp đôi num1 = 10e + 102; gấp đôi num2 = 8e + 10; kết quả = 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

Từ khóa'rictfp 'được sử dụng để buộc độ chính xác của các phép tính dấu phẩy động (float hoặc double) trong Java tuân thủ tiêu chuẩn 754 của IEEE, một cách rõ ràng. Nếu bạn không sử dụng từ khóarictfp, độ chính xác của dấu phẩy động phụ thuộc vào phần cứng của nền tảng đích.

Nếu một giao diện hoặc lớp được khai báo vớirictfp, thì tất cả các phương thức và các kiểu lồng nhau trong giao diện hoặc lớp đó đều hoàn toàn nghiêm ngặt.

Liên kết tham khảo

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.