เหตุใด Java จึงมีพื้นฐานสำหรับตัวเลขขนาดแตกต่างกัน


20

ใน Java มีชนิดดั้งเดิมสำหรับbyte, short, intและlongและสิ่งเดียวกันและfloat doubleเหตุใดจึงจำเป็นต้องให้บุคคลตั้งค่าจำนวนไบต์ที่ควรใช้สำหรับค่าดั้งเดิม ไม่สามารถกำหนดขนาดแบบไดนามิกได้ขึ้นอยู่กับว่าจำนวนที่ส่งผ่านนั้นใหญ่แค่ไหน

มี 2 ​​เหตุผลที่ฉันนึกถึง:

  1. การตั้งค่าขนาดของข้อมูลแบบไดนามิกหมายความว่ามันจะต้องสามารถเปลี่ยนแบบไดนามิกได้เช่นกัน สิ่งนี้อาจทำให้เกิดปัญหาประสิทธิภาพหรือไม่
  2. บางทีโปรแกรมเมอร์อาจไม่ต้องการให้ใครบางคนสามารถใช้ตัวเลขที่ใหญ่กว่าขนาดที่กำหนดและช่วยให้พวกเขา จำกัด มันได้

ฉันยังคงคิดว่าจะได้รับประโยชน์มากมายจากการใช้งานแบบเดี่ยวintและfloatแบบเรียบง่ายมีเหตุผลบางประการที่ Java ตัดสินใจไม่ให้ไปเส้นทางนี้หรือไม่?


4
เพื่อ downvoters, ฉันจะเพิ่มว่าคำถามนี้จะเชื่อมต่อกับคำถามที่นักวิจัยคอมไพเลอร์กำลังมองหาคำตอบ
rwong

ดังนั้นหากคุณเพิ่มหมายเลขคุณคิดว่าควรเปลี่ยนประเภทแบบไดนามิกหรือไม่ ฉันต้องการเปลี่ยนประเภทหรือไม่ ถ้าจำนวนนั้นถูกเตรียมใช้งานเป็น intUnknown alpha = a + b; คุณได้รับมันจะยากเล็กน้อยในการรวบรวม ทำไมจาวานี้ถึงเฉพาะเจาะจง?
paparazzo

@Pararazzi มีภาษาการเขียนโปรแกรมและสภาพแวดล้อมการดำเนินการที่มีอยู่ (คอมไพเลอร์, ล่าม ฯลฯ ) ที่จะจัดเก็บจำนวนเต็มความกว้างแบบไดนามิกขึ้นอยู่กับค่าที่แท้จริงคือขนาดใหญ่ (เช่นผลของการดำเนินการเพิ่มเติม) ผลที่ตามมาคือ: รหัสที่จะดำเนินการบน CPU นั้นซับซ้อนมากขึ้น ขนาดของจำนวนเต็มนั้นจะเป็นแบบไดนามิก การอ่านจำนวนเต็มความกว้างแบบไดนามิกจากหน่วยความจำอาจต้องการมากกว่าหนึ่งการเดินทาง structs (วัตถุ) และอาร์เรย์ที่มีจำนวนเต็มความกว้างแบบไดนามิกภายในเขตข้อมูล / องค์ประกอบอาจมีขนาดแบบไดนามิกเช่นกัน
rwong

1
@tofro ฉันไม่เข้าใจ เพียงแค่ส่งตัวเลขในรูปแบบใดก็ได้ที่คุณต้องการ: ทศนิยม, เลขฐานสอง, ฯลฯ การทำให้เป็นอันดับเป็นเรื่องที่เกี่ยวข้องอย่างสมบูรณ์
Gardenhead

1
@gardenhead มันเป็นมุมฉากใช่ แต่ ... เพียงแค่พิจารณากรณีที่คุณต้องการสื่อสารระหว่างเซิร์ฟเวอร์ที่เขียนใน Java และไคลเอนต์ที่เขียนด้วย C แน่นอนว่าสิ่งนี้สามารถแก้ไขได้ด้วยโครงสร้างพื้นฐานเฉพาะ เช่นมีสิ่งที่เหมือนdevelopers.google.com/protocol-buffers แต่นี่เป็นค้อนขนาดใหญ่สำหรับถั่วขนาดเล็กของการถ่ายโอนจำนวนเต็มผ่านเครือข่าย (ฉันรู้ว่านี่ไม่ใช่ข้อโต้แย้งที่แข็งแกร่งที่นี่ แต่อาจเป็นประเด็นที่ควรพิจารณา - การพูดคุยรายละเอียดเกินขอบเขตของความคิดเห็น)
Marco13

คำตอบ:


16

เช่นเดียวกับแง่มุมต่าง ๆ ของการออกแบบภาษามันเป็นการแลกเปลี่ยนกับความสง่างามที่มีต่อประสิทธิภาพ (ไม่พูดถึงอิทธิพลทางประวัติศาสตร์จากภาษาก่อนหน้า)

ทางเลือก

มันเป็นไปได้ (และค่อนข้างง่าย) natอย่างแน่นอนที่จะทำให้การเขียนโปรแกรมภาษาที่มีเพียงชนิดเดียวของจำนวนธรรมชาติ ภาษาการเขียนโปรแกรมเกือบทั้งหมดที่ใช้สำหรับการศึกษาเชิงวิชาการ (เช่น PCF, System F) มีประเภทหมายเลขเดียวนี้ซึ่งเป็นคำตอบที่สวยงามยิ่งกว่าที่คุณคาดเดา แต่การออกแบบภาษาในทางปฏิบัติไม่ได้เกี่ยวกับความสง่างามเท่านั้น เราต้องพิจารณาถึงประสิทธิภาพด้วย (ขอบเขตซึ่งการพิจารณานั้นขึ้นอยู่กับการประยุกต์ใช้ภาษาที่ต้องการ) ประสิทธิภาพประกอบด้วยข้อ จำกัด ด้านเวลาและพื้นที่

ข้อ จำกัด ของพื้นที่

การให้โปรแกรมเมอร์เลือกจำนวนไบต์ล่วงหน้าสามารถประหยัดพื้นที่ในโปรแกรมที่ จำกัด หน่วยความจำ หากตัวเลขทั้งหมดของคุณจะน้อยกว่า 256 คุณสามารถใช้ 8 ครั้งได้มากbyteถึงlongs หรือใช้ที่เก็บข้อมูลที่บันทึกไว้สำหรับวัตถุที่ซับซ้อนมากขึ้น ผู้พัฒนาแอปพลิเคชัน Java มาตรฐานไม่ต้องกังวลกับข้อ จำกัด เหล่านี้ แต่เกิดขึ้น

อย่างมีประสิทธิภาพ

แม้ว่าเราจะไม่สนใจพื้นที่เรายังคงถูก จำกัด โดย CPU ซึ่งมีเพียงคำแนะนำที่ทำงานกับจำนวนไบต์คงที่ (8 ไบต์บนสถาปัตยกรรม 64 บิต) นั่นหมายความว่าแม้การจัดเตรียมlongชนิด8 ไบต์เดียวจะทำให้การใช้ภาษาง่ายขึ้นอย่างมีนัยสำคัญยิ่งกว่าการมีประเภทจำนวนธรรมชาติที่ไม่ จำกัด โดยสามารถแมปการดำเนินการทางคณิตศาสตร์โดยตรงกับคำสั่ง CPU พื้นฐานเดียว หากคุณอนุญาตให้โปรแกรมเมอร์ใช้ตัวเลขขนาดใหญ่โดยพลการดังนั้นการคำนวณทางคณิตศาสตร์เดียวจะต้องถูกแมปกับลำดับของคำสั่งที่ซับซ้อนของเครื่องซึ่งจะทำให้โปรแกรมช้าลง นี่คือจุด (1) ที่คุณนำขึ้นมา

ประเภทจุดลอยตัว

การสนทนามีเพียงจำนวนเต็มที่เกี่ยวข้องเท่านั้น ประเภทจุดลอยตัวเป็นสัตว์ที่มีความซับซ้อนและมีความหมายที่ลึกซึ้งมาก ดังนั้นแม้ว่าเราจะสามารถแทนที่int, longและshort, byteด้วยnatประเภทเดียวได้อย่างง่ายดายแต่ก็ยังไม่ชัดเจนว่าประเภทของตัวเลขทศนิยมคืออะไร ตัวเลขเหล่านี้ไม่ใช่ของจริงอย่างชัดเจนเนื่องจากไม่มีจำนวนจริงในภาษาการเขียนโปรแกรม ตัวเลขเหล่านี้ไม่ได้เป็นจำนวนตรรกยะ (แม้ว่าจะเป็นแบบตรงไปตรงมาเพื่อสร้างประเภทเหตุผลหากต้องการ) โดยพื้นฐานแล้ว IEEE ตัดสินใจหาวิธีประมาณจำนวนจริงและภาษาทั้งหมด (และโปรแกรมเมอร์) ติดอยู่กับพวกเขานับตั้งแต่

สุดท้าย:

บางทีโปรแกรมเมอร์อาจไม่ต้องการให้ใครบางคนสามารถใช้ตัวเลขที่ใหญ่กว่าขนาดที่กำหนดและช่วยให้พวกเขา จำกัด มันได้

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


2
กุญแจสำคัญของความจริงที่เรามีคือการมีฮาร์ดแวร์เฉพาะสำหรับพวกเขา
jk

นอกจากนี้การเข้ารหัสขอบเขตตัวเลขในประเภทจะเกิดขึ้นอย่างแน่นอนในภาษาประเภทพึ่งพาและในระดับที่น้อยกว่าภาษาอื่น ๆ เช่น enums
jk

3
Enums ไม่เท่ากับจำนวนเต็ม Enums เป็นเพียงโหมดของการใช้ผลรวมชนิด ความจริงที่ว่าบางภาษาเข้ารหัสอย่างโปร่งใส enums เป็นจำนวนเต็มเป็นข้อบกพร่องทางภาษาไม่ใช่คุณสมบัติที่ใช้ประโยชน์ได้
Gardenhead

1
ฉันไม่คุ้นเคยกับ Ada ฉันสามารถ จำกัด จำนวนเต็มเป็นประเภทใดก็ได้เช่นtype my_type = int (7, 2343)?
Gardenhead

1
อ๋อ ไวยากรณ์จะเป็น: ประเภท my_type อยู่ในช่วง 7..2343
Devsman

9

เหตุผลก็คือง่ายมาก: มีประสิทธิภาพ ได้หลายวิธี

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

  2. ค่าใช้จ่ายที่ไม่ได้รับการรับรองในระบบ 32 บิต:หากการตัดสินใจทำแผนที่ทุกอย่างเป็นขนาดคงที่ 64 บิตนี่จะกำหนดบทลงโทษอย่างมากสำหรับสถาปัตยกรรม 32- บิตที่ต้องใช้วงจรนาฬิกามากขึ้นเพื่อดำเนินการ 64- การทำงานแบบบิตมากกว่าการดำเนินการแบบ 32 บิต

  3. ความสิ้นเปลืองหน่วยความจำ:มีฮาร์ดแวร์จำนวนมากอยู่ที่นั่นซึ่งไม่พิถีพิถันเกี่ยวกับการจัดเรียงหน่วยความจำ (สถาปัตยกรรม Intel x86 และ x64 เป็นตัวอย่างของสิ่งนั้น) ดังนั้นอาร์เรย์ 100 ไบต์บนฮาร์ดแวร์นั้นสามารถครอบครองหน่วยความจำได้เพียง 100 ไบต์ อย่างไรก็ตามหากคุณไม่มีไบต์อีกต่อไปและคุณจะต้องใช้เวลานานกว่านั้นอาร์เรย์เดียวกันจะมีลำดับความจำที่มากขึ้น และอาร์เรย์ไบต์เป็นเรื่องธรรมดามาก

  4. การคำนวณขนาดตัวเลข:ความคิดของคุณในการกำหนดขนาดของจำนวนเต็มแบบไดนามิกขึ้นอยู่กับว่าตัวเลขที่ส่งผ่านมีขนาดใหญ่เกินไปนั้นง่ายเกินไป ไม่มีจุดเดียวของ "การผ่าน" ตัวเลข การคำนวณจำนวนที่ต้องดำเนินการในช่วงรันไทม์สำหรับการดำเนินการแต่ละครั้งที่อาจต้องใช้ผลลัพธ์ที่มีขนาดใหญ่กว่าทุกครั้งที่คุณเพิ่มจำนวนทุกครั้งที่คุณเพิ่มตัวเลขสองครั้งทุกครั้งที่คุณคูณสอง ตัวเลข ฯลฯ

  5. การดำเนินการกับจำนวนที่มีขนาดแตกต่างกัน:จากนั้นการมีจำนวนขนาดที่แตกต่างกันที่อาจลอยไปมาในหน่วยความจำจะทำให้การดำเนินงานทั้งหมดซับซ้อน: ถึงแม้จะเปรียบเทียบตัวเลขสองตัวเพียงอย่างเดียวก็ตาม ขนาดและหากไม่ใช่ให้ปรับขนาดที่เล็กกว่าให้ตรงกับขนาดที่ใหญ่กว่า

  6. การดำเนินการที่ต้องการขนาดตัวถูกดำเนินการที่เฉพาะเจาะจง:การดำเนินการบิตที่ชาญฉลาดบางอย่างขึ้นอยู่กับจำนวนเต็มที่มีขนาดเฉพาะ หากไม่มีขนาดที่กำหนดไว้ล่วงหน้าการดำเนินการเหล่านี้จะต้องถูกจำลอง

  7. ค่าโสหุ้ยของ polymorphism:การเปลี่ยนขนาดของตัวเลขที่รันไทม์เป็นหลักหมายความว่ามันจะต้องเป็น polymorphic ในทางกลับกันนี้หมายความว่ามันไม่สามารถเป็นแบบดั้งเดิมขนาดคงที่จัดสรรบนสแต็กมันจะต้องเป็นวัตถุจัดสรรในกอง มันไม่มีประสิทธิภาพมากนัก (อ่าน # 1 อีกครั้งด้านบน)


6

เพื่อหลีกเลี่ยงการทำซ้ำจุดที่กล่าวถึงในคำตอบอื่น ๆ ฉันจะพยายามร่างมุมมองหลายมุมแทน

จากมุมมองการออกแบบภาษา

  • แน่นอนว่ามันเป็นไปได้ที่จะออกแบบและใช้ภาษาการเขียนโปรแกรมและสภาพแวดล้อมการดำเนินการที่จะรองรับผลการดำเนินการจำนวนเต็มโดยอัตโนมัติที่ไม่พอดีกับความกว้างของเครื่อง
  • เป็นตัวเลือกของนักออกแบบภาษาว่าจะทำให้จำนวนเต็มความกว้างแบบไดนามิกเป็นประเภทจำนวนเต็มเริ่มต้นสำหรับภาษานี้หรือไม่
  • อย่างไรก็ตามผู้ออกแบบภาษาจะต้องพิจารณาข้อเสียดังต่อไปนี้:
    • ซีพียูจะต้องรันโค้ดเพิ่มเติมซึ่งใช้เวลามากกว่า อย่างไรก็ตามเป็นไปได้ที่จะปรับให้เหมาะสมสำหรับกรณีที่พบบ่อยที่สุดซึ่งจำนวนเต็มพอดีกับคำของเครื่องเดียว ดูการแสดงตัวชี้แท็ก
    • ขนาดของจำนวนเต็มนั้นจะเป็นแบบไดนามิก
    • การอ่านจำนวนเต็มความกว้างแบบไดนามิกจากหน่วยความจำอาจต้องเดินทางมากกว่าหนึ่งครั้ง
    • Structs (วัตถุ) และอาร์เรย์ที่มีจำนวนเต็มความกว้างแบบไดนามิกภายในเขตข้อมูล / องค์ประกอบของพวกเขาจะมีขนาดทั้งหมด (ครอบครอง) ที่เป็นแบบไดนามิกเช่นกัน

เหตุผลทางประวัติศาสตร์

นี้จะกล่าวถึงแล้วในบทความวิกิพีเดียเกี่ยวกับประวัติศาสตร์ของ Java และยังมีการกล่าวถึงในเวลาสั้น ๆคำตอบของ Marco13

ฉันจะชี้ให้เห็นว่า:

  • นักออกแบบภาษาจะต้องเล่นปาหี่ระหว่างสุนทรียศาสตร์และความคิดในทางปฏิบัติ ความคิดด้านสุนทรียภาพต้องการออกแบบภาษาที่ไม่เป็นปัญหาที่รู้จักกันดีเช่นปัญหาจำนวนเต็มล้น ความคิดในทางปฏิบัติเตือนนักออกแบบว่าภาษาการเขียนโปรแกรมจำเป็นต้องดีพอที่จะใช้งานแอพพลิเคชั่นซอฟต์แวร์ที่มีประโยชน์และเพื่อทำงานร่วมกับส่วนซอฟต์แวร์อื่น ๆ ที่ใช้งานในภาษาต่างๆ
  • ภาษาการเขียนโปรแกรมที่ต้องการจับส่วนแบ่งการตลาดจากภาษาการเขียนโปรแกรมที่เก่ากว่าอาจมีแนวโน้มที่จะเป็นประโยชน์มากกว่า สิ่งหนึ่งที่เป็นไปได้คือพวกเขาเต็มใจที่จะรวมหรือยืมโครงสร้างและรูปแบบการเขียนโปรแกรมที่มีอยู่จากภาษาเก่าเหล่านั้น

เหตุผลด้านประสิทธิภาพ

ประสิทธิภาพมีความสำคัญเมื่อใด

  • เมื่อคุณตั้งใจจะโฆษณาภาษาโปรแกรมที่เหมาะสำหรับการพัฒนาแอพพลิเคชั่นขนาดใหญ่
  • เมื่อคุณต้องการทำงานกับสิ่งของชิ้นเล็ก ๆ นับล้านและพันล้านชิ้นซึ่งประสิทธิภาพเพิ่มขึ้นทุกบิต
  • เมื่อคุณต้องการแข่งขันกับภาษาการเขียนโปรแกรมอื่นภาษาของคุณจำเป็นต้องดำเนินการอย่างเหมาะสม - มันไม่จำเป็นต้องดีที่สุด แต่แน่นอนว่ามันจะช่วยให้คุณใกล้เคียงกับประสิทธิภาพที่ดีที่สุด

ประสิทธิภาพของการจัดเก็บ (ในหน่วยความจำหรือบนดิสก์)

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

ประสิทธิภาพของการดำเนินการ (ภายใน CPU หรือระหว่าง CPU และหน่วยความจำ)

  • กล่าวถึงแล้วในคำตอบของ gardenhead
  • หากโปรแกรมต้องการประมวลผลอาร์เรย์ขนาดเล็กจำนวนมากที่จัดเก็บอย่างต่อเนื่องประสิทธิภาพของการแสดงในหน่วยความจำมีผลโดยตรงต่อประสิทธิภาพการทำงานเนื่องจากข้อมูลจำนวนมากทำให้ปริมาณงานระหว่าง CPU และหน่วยความจำกลายเป็นปัญหาคอขวด ในกรณีนี้การบรรจุข้อมูลหนาแน่นมากขึ้นหมายความว่าการดึงข้อมูลแคชบรรทัดเดียวสามารถดึงข้อมูลได้มากขึ้น
  • อย่างไรก็ตามการใช้เหตุผลนี้ไม่สามารถใช้งานได้หากข้อมูลไม่ได้ถูกจัดเก็บหรือประมวลผลอย่างต่อเนื่อง

ความจำเป็นในการเขียนโปรแกรมภาษาเพื่อให้เป็นนามธรรมสำหรับจำนวนเต็มขนาดเล็กแม้ว่าจะ จำกัด เฉพาะบริบท

  • ความต้องการเหล่านี้มักเกิดขึ้นในการพัฒนาซอฟต์แวร์ห้องสมุดรวมถึงห้องสมุดมาตรฐานของภาษา ด้านล่างมีหลายกรณีดังกล่าว

การทำงานร่วมกัน

  • บ่อยครั้งที่ภาษาการเขียนโปรแกรมระดับสูงจำเป็นต้องมีปฏิสัมพันธ์กับระบบปฏิบัติการหรือซอฟต์แวร์ (ไลบรารี) ที่เขียนด้วยภาษาระดับต่ำกว่าอื่น ๆ ภาษาระดับต่ำกว่าเหล่านี้มักจะสื่อสารโดยใช้"structs"ซึ่งเป็นข้อกำหนดที่เข้มงวดของเค้าโครงหน่วยความจำของระเบียนที่ประกอบด้วยเขตข้อมูลที่แตกต่างกัน
  • ตัวอย่างเช่นภาษาระดับสูงกว่าอาจต้องระบุว่าฟังก์ชั่นต่างประเทศบางอย่างยอมรับcharอาร์เรย์ที่มีขนาด 256 (ตัวอย่าง)
  • abstractions ที่ใช้โดยระบบปฏิบัติการและระบบไฟล์จำเป็นต้องใช้สตรีมไบต์
  • ภาษาการเขียนโปรแกรมบางภาษาเลือกที่จะให้ฟังก์ชั่นยูทิลิตี้ (เช่นBitConverter) เพื่อช่วยในการบรรจุและแกะกล่องจำนวนเต็มแคบ ๆ ให้เป็นบิตสตรีมและไบต์สตรีม
  • ในกรณีเหล่านี้ชนิดจำนวนเต็มที่แคบลงไม่จำเป็นต้องเป็นชนิดดั้งเดิมที่สร้างไว้ในภาษา แต่สามารถให้เป็นประเภทไลบรารีได้

การจัดการสตริง

  • มีแอพพลิเคชั่นที่มีวัตถุประสงค์หลักในการออกแบบเพื่อจัดการสตริง ดังนั้นประสิทธิภาพของการจัดการสตริงจึงมีความสำคัญต่อแอพพลิเคชั่นประเภทนั้น

การจัดการรูปแบบไฟล์

  • รูปแบบไฟล์จำนวนมากได้รับการออกแบบด้วยแนวคิดแบบ C ดังนั้นการใช้ฟิลด์ความกว้างแคบจึงแพร่หลาย

ความต้องการคุณภาพซอฟต์แวร์และความรับผิดชอบของโปรแกรมเมอร์

  • สำหรับแอปพลิเคชั่นหลายประเภทการขยายจำนวนเต็มอัตโนมัตินั้นไม่ใช่คุณสมบัติที่พึงประสงค์ ไม่อิ่มตัวหรือล้อมรอบ (โมดูลัส)
  • แอปพลิเคชั่นหลายประเภทจะได้รับประโยชน์จากข้อกำหนดที่ชัดเจนของโปรแกรมเมอร์เกี่ยวกับค่าอนุญาตที่ใหญ่ที่สุดในประเด็นสำคัญต่าง ๆ ของซอฟต์แวร์เช่นที่ระดับ API

พิจารณาสถานการณ์สมมติต่อไปนี้

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

บ่อยครั้งที่ซอฟต์แวร์ที่สามารถปรับขนาดของคำสั่งได้อย่างปลอดภัยจะต้องได้รับการออกแบบทางวิศวกรรมเพื่อวัตถุประสงค์ดังกล่าวพร้อมกับความซับซ้อนที่เพิ่มขึ้น มันไม่ได้มาโดยอัตโนมัติแม้ว่าปัญหาเรื่องจำนวนเต็มล้นจะถูกกำจัดไปแล้ว สิ่งนี้มาพร้อมกับการตอบคำถามในมุมมองของการออกแบบภาษา: บ่อยครั้งที่ซอฟต์แวร์ที่ปฏิเสธที่จะทำงานเมื่อเกิดการล้นจำนวนเต็มโดยไม่ตั้งใจ (โดยการโยนข้อผิดพลาดหรือข้อยกเว้น) จะดีกว่าซอฟต์แวร์ที่สอดคล้องกับการปฏิบัติการขนาดใหญ่ทางดาราศาสตร์โดยอัตโนมัติ

นี่หมายถึงมุมมองของ OP

เหตุใดจึงจำเป็นต้องให้บุคคลตั้งค่าจำนวนไบต์ที่ควรใช้สำหรับค่าดั้งเดิม

ไม่ถูกต้อง. โปรแกรมเมอร์ควรได้รับอนุญาตและบางครั้งจำเป็นต้องระบุขนาดสูงสุดที่สามารถใช้ค่าจำนวนเต็มในส่วนที่สำคัญของซอฟต์แวร์ เมื่อคำตอบของ Gardenheadชี้ให้เห็นข้อ จำกัด ตามธรรมชาติที่กำหนดโดยประเภทดั้งเดิมนั้นไม่มีประโยชน์สำหรับจุดประสงค์นี้ ภาษาต้องจัดเตรียมวิธีสำหรับโปรแกรมเมอร์ในการประกาศขนาดและบังคับใช้ข้อ จำกัด ดังกล่าว


2

ทุกอย่างมาจากฮาร์ดแวร์

ไบต์เป็นหน่วยที่เล็กที่สุดของหน่วยความจำบนฮาร์ดแวร์ส่วนใหญ่

ทุกประเภทที่คุณเพิ่งพูดถึงนั้นสร้างจากหลายไบต์

ไบต์คือ 8 บิต เมื่อคุณสามารถแสดง 8 booleans แต่คุณไม่สามารถค้นหาทีละครั้ง คุณอยู่ 1 คุณกำลังพูดถึงทั้ง 8

มันเคยง่ายขนาดนั้น แต่จากนั้นเราเปลี่ยนจากบัส 8 บิตเป็น 16, 32 และตอนนี้ 64 บิตบัส

ซึ่งหมายความว่าในขณะที่เรายังคงอยู่ที่ระดับไบต์เราไม่สามารถเรียกข้อมูลไบต์เดียวจากหน่วยความจำอีกต่อไปโดยไม่ได้รับไบต์ข้างเคียง

ประสบกับฮาร์ดแวร์นี้นักออกแบบภาษาเลือกที่จะให้เราเลือกประเภทที่อนุญาตให้เราเลือกประเภทที่เหมาะสมกับฮาร์ดแวร์

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

Java พยายามทำสิ่งนี้จริงๆ ไบต์ถูกเลื่อนระดับเป็น Ints โดยอัตโนมัติ ความจริงที่จะผลักดันคุณถั่วในครั้งแรกที่คุณพยายามที่จะทำงานอย่างจริงจังในนั้น

เหตุใดมันจึงทำงานได้ไม่ดี

จุดขายที่ยิ่งใหญ่ของ Java ย้อนกลับไปในแต่ละวันที่คุณสามารถนั่งลงด้วยอัลกอริทึม C ที่รู้จักกันดีพิมพ์มันขึ้นมาใน Java และด้วยการปรับแต่งเล็กน้อยมันจะทำงานได้ และ C นั้นใกล้กับฮาร์ดแวร์มาก

การรักษาขนาดการเรียงตัวของอินทิกรัลไม่ได้ทำงานร่วมกัน

ดังนั้นพวกเขาสามารถมี พวกเขาไม่ได้

บางทีโปรแกรมเมอร์อาจไม่ต้องการให้ใครบางคนสามารถใช้ตัวเลขที่ใหญ่กว่าขนาดที่กำหนดและช่วยให้พวกเขา จำกัด มันได้

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

Java ไม่ใช่ภาษานั้น


" ภาษาสามารถไปไกลเท่าที่จะอบขอบเขตโดยพลการในประเภทของพวกเขา " และแน่นอน Pascal มีรูปแบบของสิ่งนี้กับประเภทย่อย
Peter Taylor

1

น่าจะเป็นเหตุผลสำคัญที่ทำให้ประเภทเหล่านี้มีอยู่ใน Java นั้นง่ายและไม่เป็นปัญหาทางเทคนิค:

C และ C ++ มีประเภทเหล่านี้ด้วย!

แม้ว่าจะเป็นการยากที่จะพิสูจน์ว่านี่คือเหตุผล แต่ก็มีหลักฐานที่ชัดเจนว่าอย่างน้อย: ข้อกำหนดภาษาของ Oak (เวอร์ชั่น 0.2) มีข้อความต่อไปนี้:

3.1 ประเภทจำนวนเต็ม

จำนวนเต็มในภาษา Oak มีความคล้ายคลึงกับ C และ C ++ โดยมีข้อยกเว้นสองประการ: จำนวนเต็มทุกชนิดเป็นเครื่องที่ไม่ขึ้นอยู่กับคำจำกัดความดั้งเดิมบางอย่างที่มีการเปลี่ยนแปลงเพื่อสะท้อนการเปลี่ยนแปลงในโลกนับตั้งแต่เปิดตัว C ชนิดจำนวนเต็มสี่ชนิดมีความกว้าง 8, 16, 32 และ 64 บิตและมีการเซ็นชื่อเว้นแต่จะมีคำนำหน้าโดยunsignedตัวปรับ

ดังนั้นคำถามสามารถต้มลงไปที่:

ทำไมสั้น, int และคิดค้นมานานใน C?

ฉันไม่แน่ใจว่าคำตอบของคำถามในจดหมายเป็นที่น่าพอใจในบริบทของคำถามที่ถามที่นี่หรือไม่ แต่เมื่อใช้ร่วมกับคำตอบอื่น ๆ ที่นี่อาจเป็นที่ชัดเจนว่าสามารถเป็นประโยชน์ในการมีประเภทเหล่านี้ (ไม่ว่าการดำรงอยู่ของพวกเขาใน Java เป็นเพียงมรดกจาก C / C ++)

เหตุผลที่สำคัญที่สุดที่ฉันคิดได้คือ

  • ไบต์เป็นหน่วยความจำที่อยู่ได้น้อยที่สุด (ดังที่ CandiedOrange กล่าวไว้แล้ว) A byteเป็นหน่วยการสร้างพื้นฐานของข้อมูลซึ่งสามารถอ่านได้จากไฟล์หรือผ่านเครือข่าย การเป็นตัวแทนที่ชัดเจนของสิ่งนี้ควรมีอยู่ (และมันมีอยู่ในภาษาส่วนใหญ่แม้บางครั้งมันก็จะปลอมตัว)

  • มันเป็นความจริงที่จริงแล้วในทางปฏิบัติมันจะสมเหตุสมผลที่จะแสดงเขตข้อมูลทั้งหมดและตัวแปรโลคัลโดยใช้ชนิดเดียวและเรียกใช้ประเภทintนี้ มีคำถามที่เกี่ยวข้องเกี่ยวกับสิ่งนั้นใน stackoverflow: ทำไม Java API จึงใช้ int แทนที่จะเป็นแบบสั้นหรือแบบไบต์ . ดังที่ฉันได้กล่าวไปแล้วในคำตอบของฉันนั่นคือเหตุผลหนึ่งที่มีประเภทที่เล็กกว่า ( byteและshort) คือคุณสามารถสร้างอาร์เรย์ของประเภทเหล่านี้ได้: Java มีตัวแทนของอาร์เรย์ที่ยังค่อนข้าง "ใกล้กับฮาร์ดแวร์" ตรงกันข้ามกับภาษาอื่น ๆ (และตรงกันข้ามกับอาร์เรย์ของวัตถุเช่นInteger[n]อาร์เรย์) int[n]อาร์เรย์ไม่ใช่ชุดของการอ้างอิงที่ค่าต่างๆกระจัดกระจายไปทั่วฮีป แต่มันจะในทางปฏิบัติเป็นบล็อกต่อเนื่องของn*4ไบต์ - หน่วยความจำหนึ่งอันที่มีขนาดที่รู้จักและโครงร่างข้อมูล เมื่อคุณมีทางเลือกในการเก็บ 1,000 ไบต์ในการเก็บรวบรวมวัตถุค่าจำนวนเต็มโดยพลการหรือในbyte[1000](ซึ่งใช้ 1,000 ไบต์) หลังอาจบันทึกหน่วยความจำบางอย่างแน่นอน (ข้อดีอื่น ๆ ของสิ่งนี้อาจมีความละเอียดมากกว่าและชัดเจนเมื่อเชื่อมต่อ Java กับไลบรารีดั้งเดิม)


เกี่ยวกับประเด็นที่คุณถามโดยเฉพาะเกี่ยวกับ:

ไม่สามารถกำหนดขนาดแบบไดนามิกได้ขึ้นอยู่กับว่าจำนวนที่ส่งผ่านนั้นใหญ่แค่ไหน

การตั้งค่าขนาดของข้อมูลแบบไดนามิกหมายความว่ามันจะต้องสามารถเปลี่ยนแบบไดนามิกได้เช่นกัน สิ่งนี้อาจทำให้เกิดปัญหาประสิทธิภาพหรือไม่

อาจเป็นไปได้ที่จะกำหนดขนาดของตัวแปรแบบไดนามิกหากพิจารณาว่าจะออกแบบภาษาการเขียนโปรแกรมใหม่ทั้งหมดตั้งแต่เริ่มต้น ฉันไม่ได้เป็นผู้เชี่ยวชาญในการก่อสร้างคอมไพเลอร์ แต่คิดว่ามันจะยากที่จะคอลเลกชัน mangage สมเหตุสมผลของการเปลี่ยนแปลงแบบไดนามิกประเภท - โดยเฉพาะอย่างยิ่งเมื่อคุณมีอย่างยิ่งภาษาพิมพ์ ดังนั้นมันอาจจะต้มลงไปถึงตัวเลขทั้งหมดที่ถูกเก็บไว้ใน "ประเภทข้อมูลตัวเลขทั่วไปที่มีความแม่นยำโดยพลการ" ซึ่งแน่นอนว่าจะส่งผลกระทบต่อประสิทธิภาพการทำงาน แน่นอนว่ายังมีการเขียนโปรแกรมภาษาที่มีการพิมพ์มั่นและ / หรือนำเสนอรูปแบบจำนวนขนาดโดยพลการ แต่ฉันไม่คิดว่าจะมีการเขียนโปรแกรมภาษาวัตถุประสงค์ที่แท้จริงทั่วไปที่ไปด้วยวิธีนี้


หมายเหตุด้านข้าง:

  • คุณอาจสงสัยเกี่ยวกับโมดิunsignedฟายเออร์ที่กล่าวถึงในข้อมูลจำเพาะของโอ๊ก ในความเป็นจริงมันยังมีข้อสังเกต: " unsignedยังไม่ได้ใช้งาน แต่อาจไม่เป็นเช่นนั้น" . และพวกเขาพูดถูก

  • นอกจากจะสงสัยว่าทำไม C / C ++ มีประเภทจำนวนเต็มเหล่านี้แตกต่างกันที่ทุกท่านอาจสงสัยว่าทำไมพวกเขาพวกเขา messed ขึ้นเพื่อให้น่ากลัวที่คุณไม่เคยรู้ว่าหลายบิตintมี เหตุผลสำหรับเรื่องนี้มักจะเกี่ยวข้องกับประสิทธิภาพและสามารถค้นหาได้ที่อื่น


0

มันแสดงให้เห็นอย่างแน่นอนว่าคุณยังไม่ได้สอนเกี่ยวกับการแสดงและสถาปัตยกรรม

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

การเพิกเฉยต่อความสำคัญของขนาดข้อมูลจะกระทบกับประสิทธิภาพเสมอคุณต้องใช้ทรัพยากรให้มากที่สุดเท่าที่จำเป็น แต่ไม่มากไปกว่านี้เสมอ!

นั่นคือความแตกต่างระหว่างโปรแกรมหรือระบบที่ทำสิ่งที่ง่ายและไม่มีประสิทธิภาพอย่างไม่น่าเชื่อต้องใช้ทรัพยากรจำนวนมากและการใช้ระบบนั้นมีค่าใช้จ่ายสูงมาก หรือระบบที่ทำงานได้มาก แต่ทำงานได้เร็วกว่าที่คนอื่น ๆ และถูกจริงๆที่จะทำงาน


0

มีเหตุผลที่ดีสองสามข้อ

(1) ในขณะที่การจัดเก็บของตัวแปรไบต์หนึ่งโองการหนึ่งยาวไม่สำคัญการเก็บข้อมูลนับล้านในอาร์เรย์มีความสำคัญมาก

(2) "เลขคณิตฮาร์ดแวร์ดั้งเดิม" โดยยึดตามขนาดจำนวนเต็มอาจมีประสิทธิภาพมากขึ้นและสำหรับอัลกอริทึมบางอย่างในบางแพลตฟอร์มซึ่งอาจมีความสำคัญ

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