เมื่อใดที่ฉันควรใช้คำว่า "เข้มงวด" ใน java?


258

ฉันได้ค้นหาสิ่งนี้แล้ว แต่ไม่มีใครมีตัวอย่างของเมื่อคุณจะใช้strictfpคำหลักใน Java หรือไม่? มีใครพบการใช้งานนี้จริงหรือ

จะมีผลข้างเคียงของการใส่ลงในการดำเนินการจุดลอยตัวของฉันทั้งหมดหรือไม่


1
เสมอเว้นแต่คุณจะต้องการประสิทธิภาพมากกว่าที่คุณต้องการให้ทำซ้ำได้จริง
พลวง

1
@Antimony - หรือความแม่นยำ / ความถูกต้อง ตัวอย่างเช่น x86 / x64 ให้ใช้การลงทะเบียนจุดลอยตัว 80 บิตภายในเพื่อให้ผลลัพธ์มีความแม่นยำมากขึ้นสำหรับการคำนวณที่ยาวนานโดยไม่ต้องเข้มงวด fp
Robert Fraser

1
@ Robert จริง ๆ แล้ว spec รับประกันความแม่นยำที่ จำกัด ของ mantissa ข้อแตกต่างคือมันอาจใช้ความแม่นยำเลขชี้กำลังขนาดใหญ่กว่าปกติซึ่งมีความแตกต่างในกรณีที่หายากเนื่องจากการปัดเศษสองครั้ง
พลวง

ฉันคิดว่านอกเหนือจากตัวเลือกในการโรยตัวแก้ไขที่มีประโยชน์นี้ไปทั่วข้อต่อแล้ว sfloat & sdouble primitive เข้มงวด ff datatypes อาจเป็นความคิดที่ดี
theRiley

คำตอบ:


274

Strictfp ทำให้แน่ใจว่าคุณได้รับผลลัพธ์ที่เหมือนกันแน่นอนจากการคำนวณจุดลอยตัวของคุณในทุกแพลตฟอร์ม หากคุณไม่ได้ใช้เข้มงวดffการใช้งาน JVM มีอิสระที่จะใช้ความแม่นยำเป็นพิเศษหากมี

จาก JLS :

ภายในนิพจน์ที่เข้มงวดของ FP ค่ากลางทั้งหมดจะต้องเป็นองค์ประกอบของชุดค่าลอยหรือชุดค่าคู่หมายความว่าผลลัพธ์ของนิพจน์ที่เข้มงวดของ FP ทั้งหมดจะต้องเป็นค่าที่ทำนายไว้โดยเลขคณิต IEEE 754 บนตัวถูกดำเนินการโดยใช้รูปแบบเดี่ยวและคู่ . ภายในนิพจน์ที่ไม่ใช่ FP-เข้มงวดบาง leeway จะได้รับสำหรับการใช้งานเพื่อใช้ช่วงเลขชี้กำลังขยายเพื่อแสดงผลลัพธ์กลาง; ผลกระทบสุทธิการพูดอย่างคร่าว ๆ ก็คือการคำนวณอาจทำให้เกิด "คำตอบที่ถูกต้อง" ในสถานการณ์ที่การใช้ชุดลอยพิเศษหรือชุดมูลค่าสองเท่าอาจส่งผลให้เกิดการล้นหรืออันเดอร์

ในคำอื่น ๆ มันเป็นเรื่องของการทำให้แน่ใจว่าเขียนเมื่อเรียกใช้ทุกที่จริงหมายถึงการเขียนเมื่อได้รับอย่างเท่าเทียมกัน-ผิดผลลัพธ์ทุกที่

ด้วยผลลัพธ์ที่เข้มงวดของคุณจะสามารถพกพาได้โดยที่ไม่น่าจะแม่นยำ


28
ใช้สำหรับผลลัพธ์ทางวิทยาศาสตร์ที่ทำซ้ำได้และการทดสอบหน่วยบิตแน่นอน
Aleksandr Dubinsky

1
"หากคุณไม่ใช้เข้มงวดอย่างเข้มงวดการใช้ JVM นั้นให้ใช้ความแม่นยำเป็นพิเศษหากมี" คุณทำให้เสียงนั้นเป็นสิ่งที่ไม่ดี: P
AMDG

@LinkTheProgrammer มันอาจเป็นสิ่งที่ไม่ดีอย่างแน่นอน
ทิม

@TimCastelijns ฉันคิดว่าHappy Wheelsเป็นข้อมูลอ้างอิงของคุณหรือไม่ การกดแป้นบันทึกไกล เนื่องจากความหลากหลายของความแม่นยำในการปรับใช้ FP-math การใช้งานจึงมีความแม่นยำในฮาร์ดแวร์ที่คล้ายคลึงกันเท่านั้น คุณสามารถตั้งชื่อปัญหาที่เหมือนจริงมากขึ้นที่เกิดจากความแปรปรวนทางคณิตศาสตร์แบบอิงดัชนี ฉันจินตนาการได้ว่าอาจเป็นเครื่องจำลองอนุภาค แต่มีอะไรอีกบ้าง
AMDG

ดังนั้นนี่หมายความว่าเราควรใช้เข้มงวด ff ในการผลิตที่เกี่ยวข้องกับหลายแพลตฟอร์ม?
เบียทริ

65

Wikipedia มีบทความที่ดีเกี่ยวกับหัวข้อนี้จริง ๆ แล้วที่นี่พร้อมลิงค์ไปยังข้อมูลจำเพาะ Java

การอ่านระหว่างบรรทัดความหมายก็คือถ้าคุณไม่ได้ระบุstrictfpดังนั้นคอมไพเลอร์ JVM และ JIT มีสิทธิ์ใช้งานเพื่อคำนวณการคำนวณทศนิยมของคุณอย่างไรก็ตามพวกเขาต้องการ เพื่อประโยชน์ของความเร็วพวกเขามักจะมอบหมายการคำนวณให้กับโปรเซสเซอร์ของคุณ ด้วยstrictfpในการคำนวณจะต้องเป็นไปตามมาตรฐาน IEEE 754 มาตรฐานทางคณิตศาสตร์ซึ่งในทางปฏิบัติอาจจะหมายถึงว่า JVM จะทำคำนวณ

ดังนั้นเหตุผลที่คุณต้องการใช้strictfp? สถานการณ์หนึ่งที่ฉันเห็นคือในแอปพลิเคชันแบบกระจาย (หรือเกมแบบผู้เล่นหลายคน) ที่การคำนวณจุดลอยตัวทั้งหมดจำเป็นต้องกำหนดไว้ล่วงหน้าไม่ว่าฮาร์ดแวร์หรือซีพียูพื้นฐานจะเป็นอย่างไร การแลกเปลี่ยนคืออะไร? เวลาดำเนินการที่เป็นไปได้มากที่สุด


5
“ ช่วงเลขชี้กำลังขยายเพิ่มเพื่อแสดงผลลัพธ์ระดับกลาง” ไม่ใช่“ ใบอนุญาตในการคำนวณการคำนวณทศนิยมของคุณอย่างไรก็ตามพวกเขาต้องการ” และในทางปฏิบัติแม้แต่strictfpการคำนวณใช้ประโยชน์จาก 8087 FPU ที่ไม่ช่วยเหลือ เป็นเพียงกรณีที่จำเป็นต้องใช้ความระมัดระวัง ดูstackoverflow.com/questions/18496560/…
Pascal Cuoq

ผมเห็นด้วยกับ @PascalCuoq Re: "ใบอนุญาตในการคำนวณการคำนวณจุดลอยตัวของคุณ แต่พวกเขาต้องการ" หากมีสิ่งใดตรงกันข้ามในกรณีนี้ดูเหมือนจะเป็นจริงเนื่องจากstrictfpมั่นใจว่าสอดคล้องกับมาตรฐาน IEEE 754 (เพื่อให้คุณได้รับผลลัพธ์เดียวกันในทุกแพลตฟอร์ม) ข้อเสียเปรียบเพียงอย่างเดียวที่ฉันเห็นคือคุณอาจสูญเสียผลประโยชน์จากการมี FPU ที่ดีจริงๆที่มีอยู่ในฮาร์ดแวร์ของคุณ
typeracer

25

ทุกอย่างเริ่มต้นด้วยเรื่องราว

เมื่อจาวาถูกพัฒนาโดย James Gosling เฮอร์เบิร์ตและทีมอื่น ๆ ของเขา พวกเขามีสิ่งที่บ้านี้ในใจที่เรียกว่าแพลตฟอร์มอิสระ พวกเขาต้องการทำไม้โอ๊ค (Java)ดีกว่านั้นมากจนมันจะทำงานเหมือนกันทุกเครื่องที่มีชุดคำสั่งต่างกันแม้กระทั่งใช้ระบบปฏิบัติการที่แตกต่างกัน แต่มีปัญหากับตัวเลขทศนิยมที่รู้จักกันว่าทศนิยมและสองเท่าในภาษาการเขียนโปรแกรม เครื่องจักรบางตัวสร้างประสิทธิภาพการกำหนดเป้าหมายในขณะที่ส่วนที่เหลือถูกกำหนดเป้าหมายความแม่นยำ ดังนั้นเครื่องจักรที่มีความแม่นยำมากกว่านั้นจึงมีขนาดของจุดลอยตัวเท่ากับ 80 บิตในขณะที่เครื่องจักรเดิม (มีประสิทธิภาพ / เร็วกว่า) มี 64 บิตเป็นสองเท่า แต่นี่เป็นแนวคิดหลักในการสร้างภาษาอิสระของแพลตฟอร์ม นอกจากนี้สิ่งนี้อาจนำไปสู่การสูญเสียความแม่นยำ / ข้อมูลเมื่อมีการสร้างรหัสในเครื่อง (มีขนาด 64 บิตเป็นสองเท่า) และทำงานบนเครื่องประเภทอื่น (มีขนาด 80 บิตเป็นสองเท่า)

สามารถปรับขนาดได้ แต่ไม่สามารถปรับขนาดได้ ดังนั้นพวกเขามาในแนวคิดของ strictfp เช่นจุดลอยเข้มงวด หากคุณใช้คีย์เวิร์ดนี้พร้อมคลาส / ฟังก์ชั่นดังนั้นจุดลอยตัวและดับเบิลของมันจะมีขนาดที่สอดคล้องกันกับเครื่องใด ๆ เช่น 32/64 บิตตามลำดับ


8
เข้มงวดfpถูกนำมาใช้ใน Java 1.2 นี่มันช้ากว่าตอนที่โอ๊คได้รับการออกแบบ
Thorbjørn Ravn Andersen

"ตัวเลขทศนิยมที่รู้จักกันว่าทศนิยม" - ทศนิยมหมายถึงฐาน 10 และไม่มีส่วนเกี่ยวข้องกับการเป็นตัวแทนทศนิยม
aioobe

21

นี่คือการอ้างอิงหลายประการ:

  • การใช้เข้มงวดf (เคล็ดลับเทคโนโลยี JDC)
  • jGuru: ตัวดัดแปลงแบบเข้มงวดคืออะไร เมื่อใดที่ฉันจะพิจารณาใช้

    โดยพื้นฐานแล้วสิ่งที่ควรคำนึงถึงคือคุณสนใจหรือไม่ว่าผลลัพธ์ของนิพจน์จุดลอยตัวในโค้ดของคุณนั้นรวดเร็วหรือคาดเดาได้ strictfpตัวอย่างเช่นถ้าคุณต้องการคำตอบที่รหัสของคุณขึ้นมาด้วยซึ่งใช้ค่าจุดลอยตัวเพื่อให้สอดคล้องในหลายแพลตฟอร์มแล้วการใช้งาน

  • เข้มงวดfp - Java อภิธานศัพท์

    ฮาร์ดแวร์จุดลอยตัวคำนวณด้วยความแม่นยำมากขึ้นและมีช่วงของค่าที่มากกว่าข้อกำหนดของ Java มันจะสับสนถ้าแพลตฟอร์มบางแห่งให้ความแม่นยำมากกว่าแพลตฟอร์มอื่น ๆ เมื่อคุณใช้โมดิstrictfpฟายเออร์ในเมธอดหรือคลาสคอมไพเลอร์จะสร้างโค้ดที่ยึดตามข้อกำหนด Java อย่างเคร่งครัดสำหรับผลลัพธ์ที่เหมือนกันในทุกแพลตฟอร์ม ข้างstrictfpนอกนั้นเป็นคนขี้เกียจเล็กน้อย แต่ไม่ใช่คนขี้เกียจที่จะใช้การ์ดป้องกันใน Pentium เพื่อให้ความแม่นยำ 80 บิต

  • และในที่สุดก็มีข้อกำหนดภาษา Java จริง, Express15.4 การแสดงออกที่เข้มงวด FP :

    ภายในนิพจน์ที่เข้มงวดของ FP ค่ากลางทั้งหมดจะต้องเป็นองค์ประกอบของชุดค่าลอยหรือชุดค่าคู่หมายความว่าผลลัพธ์ของนิพจน์ที่เข้มงวดของ FP ทั้งหมดจะต้องเป็นค่าที่ทำนายไว้โดยเลขคณิต IEEE 754 บนตัวถูกดำเนินการโดยใช้รูปแบบเดี่ยวและคู่ . ภายในนิพจน์ที่ไม่ใช่ FP-เข้มงวดบาง leeway จะได้รับสำหรับการใช้งานเพื่อใช้ช่วงเลขชี้กำลังขยายเพื่อแสดงผลลัพธ์กลาง; ผลกระทบสุทธิการพูดอย่างคร่าว ๆ ก็คือการคำนวณอาจทำให้เกิด "คำตอบที่ถูกต้อง" ในสถานการณ์ที่การใช้ชุดลอยพิเศษหรือชุดค่าสองเท่าอาจส่งผลให้เกิดการล้นหรืออันเดอร์โฟล์ว

ฉันไม่เคยใช้มันเป็นการส่วนตัว


12

ดังที่คำตอบอื่น ๆ ที่กล่าวถึงทำให้เกิดจุดลอยตัวกลางเพื่อให้สอดคล้องกับข้อกำหนด IEEE โดยเฉพาะโปรเซสเซอร์ x86 สามารถเก็บผลลัพธ์ระดับกลางด้วยความแม่นยำที่แตกต่างจากข้อมูลจำเพาะ IEEE สถานการณ์มีความซับซ้อนมากขึ้นเมื่อ JIT ทำการคำนวณที่เหมาะสมที่สุด คำสั่งนั้นอาจแตกต่างกันในแต่ละครั้งทำให้เกิดการปัดเศษที่แตกต่างกัน

ค่าโสหุ้ยที่เกิดขึ้นจากการเข้มงวด ff น่าจะเป็นตัวประมวลผลที่มาก บทความวิกิพีเดียในSSE2 นี้ดูเหมือนว่าจะมีข้อมูลเชิงลึกเกี่ยวกับปัญหา ดังนั้นหาก JIT สามารถสร้างคำสั่ง SSE เพื่อทำการคำนวณดูเหมือนว่าเข้มงวด fp จะไม่มีค่าใช้จ่ายใด ๆ

ในโครงการปัจจุบันของฉันมีบางสถานที่ที่ฉันใช้เข้มงวด มีจุดที่รังสีคอสมิคที่อาจเกิดขึ้นต้องถูกลบออกจากค่าพิกเซล หากนักวิจัยภายนอกบางคนมีค่าพิกเซลและรังสีคอสมิคที่อยู่ข้างหน้าพวกเขาควรจะได้รับค่าผลลัพธ์เดียวกันกับซอฟต์แวร์ของเรา


8
  • rictfp เป็นตัวดัดแปลงที่ จำกัด การคำนวณจุดลอยตัวตามมาตรฐาน IEEE 754

  • สิ่งนี้สามารถใช้กับคลาสทั้งหมดเช่น "publicrictfp class StrictFpModifierExample {}" หรือบนเมธอด "public void ตัวอย่างโมฆะ ()" ถ้ามันถูกใช้กับคลาสมากกว่าเมธอดทั้งหมดจะเป็นไปตาม IEEE 754 และถ้าใช้กับเมธอดนั้น ติดตาม IEEE 754

  • ทำไมมันถูกใช้ :: :: เนื่องจากแพลตฟอร์มที่แตกต่างกันมีฮาร์ดแวร์จุดลอยตัวที่แตกต่างกันซึ่งคำนวณด้วยความแม่นยำและช่วงของค่าที่มากกว่าข้อกำหนดจาวาที่ต้องการซึ่งอาจสร้างเอาต์พุตที่แตกต่างกันในรูปแบบที่ต่างกันดังนั้นจึงเป็นการยืนยันผลลัพธ์เดียวกัน plateforms

  • เข้มงวดจึงมั่นใจได้ว่าจะใช้ประโยชน์จากความเร็วและความแม่นยำของการดำเนินการจุดลอยตัวที่มีความแม่นยำสูง

  • ไม่มีข้อเสียกับคำสำคัญนี้ที่เราสามารถใช้เมื่อเราทำการคำนวณจุดลอยตัว

  • จุดสุดท้ายของฉันคือ - อะไรคือ IEEE754 ในระยะสั้น IEEE 754 กำหนดวิธีมาตรฐานสำหรับทั้งการคำนวณจุดลอยตัวและการจัดเก็บค่าจุดลอยในเดี่ยว (32- บิตใช้ใน Java ลอย) หรือสองครั้ง (64 บิตใช้ใน Java ดับเบิล) ความแม่นยำนอกจากนี้ยังกำหนดบรรทัดฐานสำหรับการคำนวณระดับกลางและสำหรับรูปแบบความแม่นยำเพิ่มเติม


2

strictfpเป็นคีย์เวิร์ดและสามารถใช้เป็นโมดิฟายเออร์ที่ไม่ได้ใช้งานสำหรับคลาสหรือเมธอด (แต่ไม่มีตัวแปร) การทำเครื่องหมายคลาสว่าstrictfpหมายความว่าโค้ดวิธีใด ๆ ในคลาสจะสอดคล้องกับกฎมาตรฐาน IEEE 754 สำหรับคะแนนลอย

หากไม่มีตัวแก้ไขนั้นจุดลอยตัวที่ใช้ในวิธีการอาจทำงานในลักษณะที่ขึ้นกับแพลตฟอร์ม ด้วยคุณสามารถคาดการณ์ว่าจุดลอยตัวของคุณจะทำงานอย่างไรโดยไม่คำนึงถึงแพลตฟอร์มพื้นฐานที่ JVM กำลังทำงานอยู่ ข้อเสียคือถ้าแพลตฟอร์มพื้นฐานรองรับความแม่นยำได้มากกว่าstrictfpวิธีการจะไม่สามารถใช้ประโยชน์จากมันได้

หากคุณไม่ได้ประกาศคลาสในขณะที่strictfpคุณยังสามารถรับstrictfpพฤติกรรมตามวิธีการโดยการประกาศวิธีการเป็นstrictfpพฤติกรรมบนพื้นฐานวิธีการโดยวิธีการด้วยการประกาศว่าเป็นวิธีการ

~ SCJP Sun®ได้รับการรับรองโปรแกรมเมอร์สำหรับ Java ™ 6 - Kathy Sierra & Bert Bates ~


0

ตัวอย่างด้านล่างอาจช่วยให้เข้าใจชัดเจนยิ่งขึ้น: ใน java เมื่อใดก็ตามที่เราใช้กำลังมองหาข้อมูลที่แม่นยำสำหรับการดำเนินการใด ๆ เช่นถ้าเราทำ double num1 = 10e + 102; double num2 = 8e + 10; ผลลัพธ์ = 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

คำหลัก 'เข้มงวดfp' ใช้เพื่อบังคับความแม่นยำของการคำนวณจุดลอยตัว (ลอยหรือสองเท่า) ใน Java ที่สอดคล้องกับมาตรฐาน 754 ของ IEEE อย่างชัดเจน หากคุณไม่ได้ใช้คำหลักเข้มงวด, ความแม่นยำจุดลอยตัวขึ้นอยู่กับฮาร์ดแวร์ของแพลตฟอร์มเป้าหมาย

หากมีการประกาศส่วนต่อประสานหรือคลาสที่เข้มงวดกับวิธีการทั้งหมดและประเภทที่ซ้อนกันภายในส่วนติดต่อหรือชั้นเรียนที่มีความเข้มงวดโดยนัย

ลิงค์อ้างอิง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.