เอกสารใดที่บอกว่าช่วงใดของ. NET BigIntegers ที่ออกแบบมาเพื่ออะไร?


12

ฉันกำลังเล่นกับ. NET BigIntegerและโดยทั่วไปฉันสงสัยว่าจำนวนใด - คำตอบโดยประมาณน่าจะดี - คือจุดเบี่ยงเบนของเส้นโค้งของ (กราฟของ (เพิ่มเวลาที่จำเป็นสำหรับการปฏิบัติการ) vs (มูลค่าของ BigInteger))?

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

ตัวอย่างเช่นสมมติว่าอาร์เรย์ได้รับการออกแบบที่มีความสามารถในการจัดการ 50 รายการ หมายความว่าถ้าฉันมี 1 รายการการดำเนินการจะเป็นเวลา f (1) และเมื่อฉันมี 2 รายการการดำเนินการคือ f (2) เวลา หากฉันมี 50 รายการการดำเนินการจะเป็นเวลา f (50) แต่เนื่องจากมันถูกออกแบบมาสำหรับการจัดการ 50 รายการเท่านั้นการดำเนินการเมื่อเรามี 51 รายการจะเป็น g (51) โดยที่ g (51)> f (51)

หากดำเนินการอย่างเหมาะสมความซับซ้อนของ BigInteger เลขคณิตควรเป็นเส้นโค้งที่ราบรื่น ตัวอย่างเช่นความซับซ้อนของเวลาในการคูณควรเป็น O (NM) โดยที่ N คือจำนวนหลักในการคูณแรกและ M คือจำนวนหลักในการคูณที่สอง แน่นอนว่ามีข้อ จำกัด ในทางปฏิบัติที่คุณสามารถเลือก N และ M ได้ขนาดใหญ่จนตัวเลขไม่พอดีกับเครื่องของคุณ

มีใครบ้าง / ไม่รู้ว่ามีเอกสารใดที่อ้างว่ามีการใช้งานเช่นนี้หรือไม่?


3
@ ผู้ลงคะแนนที่ลงคะแนนเสียงไม่ได้หมายความว่าอะไรถ้าคุณไม่สามารถแสดงความคิดเห็นได้อธิบายว่าทำไมคำถามนี้ไม่ใช่คำถามที่ดี ฉันอัปเกรดสิ่งนี้เพราะฉันไม่เห็นปัญหาใด ๆ
มัฟฟินแมน

ฉันไม่ได้ลงคะแนน แต่ฉันไม่แน่ใจว่าสิ่งที่เป็นคำถามที่นี่ คุณต้องการทราบความซับซ้อนของรันไทม์ / หน่วยความจำของการดำเนินการบน bigints (การเพิ่มการคูณการหาร ฯลฯ ) หรือไม่?
nikie

ตัวอย่างเช่นสมมติว่าอาร์เรย์ได้รับการออกแบบที่มีความสามารถในการจัดการ 50 รายการ หมายความว่าหากฉันมี 1 รายการและการดำเนินการคือเวลา f (1) และเมื่อฉันมี 2 รายการการดำเนินการคือ f (2) เวลา ถ้าฉันมีการดำเนินการ 50 รายการคือเวลา f (50) แต่เนื่องจากมันถูกออกแบบมาสำหรับการจัดการ 50 รายการเท่านั้นการดำเนินการเมื่อเรามี 51 รายการจะเป็น g (51) โดยที่ g (51)> f (51)
Pacerier

@ Charles E. Grant ใช่! นี่คือสิ่งที่ฉันกำลังพูดถึง มีคำถามใด ๆ / ไม่มีใครทราบเอกสารใด ๆ ที่อ้างว่ามีการใช้งานเช่นนี้?
Pacerier

@Pierier ฉันได้ย้ายความคิดเห็นของฉันไปยังคำตอบแล้วเพิ่มลิงก์ไปยังเอกสารที่พูดถึงสิ่งนี้
Charles E. Grant

คำตอบ:


7

หมายเลขใด ๆ ที่อาจมีขนาดใหญ่กว่า ULong.MaxValue หรือเล็กกว่า Long.MinValue ควรแสดงโดยใช้ BigInteger

ถ้าไม่ใช่ (Long.MinValue <= X <= ULong.MaxValue) จากนั้น BigInteger

BigInteger สำหรับจำนวนที่มากเกินไปเกินกว่าที่จะสามารถจัดการได้

ตัวอย่างเช่นหากจำนวนเต็มของคุณอยู่นอกช่วง Long คุณอาจใช้ BigInteger กรณีเหล่านี้หายากมากและการใช้คลาสเหล่านี้มีค่าใช้จ่ายสูงกว่าแบบดั้งเดิมอย่างมีนัยสำคัญ

ตัวอย่างเช่นlongกว้าง 64 บิตและสามารถเก็บช่วงได้: -9,223,372,036,854,775,808 ถึง 9,223,372,036,854,775,80 ulong สามารถถือ 0 ถึง 18,446,744,073,709,551,615 หากหมายเลขของคุณใหญ่กว่าหรือเล็กกว่านั้น BigInteger เป็นตัวเลือกเดียวของคุณ

ครั้งเดียวที่ฉันเห็นพวกเขาใช้ในแอพพลิเคชั่นโลกแห่งความจริงคือแอปพลิเคชัน Starchartting

ดูเพิ่มเติมที่: ช่วงดั้งเดิมใน. NET


ฉันหมายถึงแน่นอนฉันรู้ว่าเราควรใช้ primitives ปกติทุกครั้งที่เราสามารถ .. ฉันหมายถึงว่าพูดคือ BigInteger ออกแบบมาสำหรับตัวเลข 100 ครั้งใหญ่กว่า ULong.MaxValue หรือ BigInteger ถูกออกแบบมาสำหรับตัวเลข 100k คูณใหญ่กว่า ULong.MaxValue? ฉันหมายความว่าฉันรู้ว่ามันสามารถรองรับขนาดใหญ่กว่า ULong.MaxValue ได้ 100k เท่า แต่มันถูกออกแบบมาโดยคำนึงถึงช่วงนี้หรือไม่หรือมันถูกออกแบบด้วยช่วงนี้ที่ประกาศว่า
Pacerier

5
คุณไม่สามารถแสดงตัวเลขที่มากกว่าหนึ่ง ULong.MaxValue ได้โดยไม่ต้องใช้ BigInteger ดังนั้นจึงเป็นสิ่งนั้น หมายเลขใด ๆ ที่อาจมีขนาดใหญ่กว่า ULong.MaxValue ควรเป็น BigInteger
Malfist

แน่นอนมีวิธีการแสดงตัวเลขที่มากกว่า ULong.MaxValue และไม่ต้องใช้ BigInteger ฉันสามารถเขียนโครงสร้างแบบกำหนดเองที่ประกอบด้วย ULong และบูลีนและวิโอล่าฉันสามารถแสดงถึง ULong.MaxValue ได้มากถึงสองเท่า
Pacerier

ใช่ แต่มันซับซ้อนน้อยกว่าในการใช้ BigInteger และมันอาจจะไม่เร็วกว่านี้หากเร็วกว่านี้และมันจะไม่ยืดหยุ่นเท่ากับ BigInteger คุณสามารถแทนตัวเลขจำนวนมากด้วยชุดบูลีน แต่นั่นก็ซับซ้อนเกินไป
Malfist

2
@Mavrik เขาเปลี่ยนคำถามนี้เป็นคำถามที่แตกต่างไปจากคำถามที่ฉันตอบ
Malfist

4

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

ตามที่คนอื่น ๆ ชี้ให้เห็นอูลองสามารถถือระหว่าง 0 ถึง 18,446,744,073,709,551,615 และตราบใดที่คุณยังคงอยู่ในช่วงนั้นคุณสามารถทำเลขคณิตที่แน่นอน หากคุณไปเกิน 1 ช่วงนั้นคุณจะได้รับการล้นดังนั้นคำตอบสำหรับคำถามของคุณคือใช้ BigInteger หากคุณต้องการเลขคณิตที่แน่นอนและมีความเป็นไปได้ที่ผลลัพธ์ระดับกลางใด ๆ จะเกิน 18,446,744,073,709,551,615

ปัญหาส่วนใหญ่ในวิทยาศาสตร์วิศวกรรมและการเงินสามารถอยู่กับการประมาณที่บังคับโดยตัวเลขจุดลอยตัวและไม่สามารถจ่ายค่าใช้จ่ายเวลาของการคำนวณ BigInteger ได้ การคำนวณเชิงพาณิชย์ส่วนใหญ่ไม่สามารถอยู่ได้ด้วยการประมาณเลขคณิตจุดลอยตัว แต่ทำงานในช่วง 0 ถึง 18,446,744,073,709,551,615 เพื่อให้สามารถใช้เลขคณิตทั่วไปได้ BigInteger เป็นสิ่งจำเป็นเมื่อใช้อัลกอริทึมจากทฤษฎีจำนวนซึ่งรวมถึงสิ่งต่าง ๆ เช่นการเข้ารหัส (คิดว่า 50 หลักสำคัญจำนวน) บางครั้งมันก็ถูกใช้ในแอพพลิเคชั่นเชิงพาณิชย์เมื่อต้องการการคำนวณที่แม่นยำความเร็วไม่สำคัญเกินไปและการตั้งค่าระบบจุดทศนิยมคงที่ที่เหมาะสมนั้นเป็นปัญหามากเกินไป

หากดำเนินการอย่างเหมาะสมความซับซ้อนของ BigInteger เลขคณิตควรเป็นเส้นโค้งที่ราบรื่น ตัวอย่างเช่นความซับซ้อนของเวลาในการคูณควรเป็น O (NM) โดยที่ N คือจำนวนหลักในการคูณแรกและ M คือจำนวนหลักในการคูณที่สอง แน่นอนว่ามีข้อ จำกัด ในทางปฏิบัติที่คุณสามารถเลือก N และ M ได้ขนาดใหญ่จนตัวเลขไม่พอดีกับเครื่องของคุณ

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


4

ขีด จำกัด หน่วยความจำ

BigInteger ขึ้นอยู่กับ int array สำหรับการจัดเก็บ สมมติว่าข้อ จำกัด ทางทฤษฎีสำหรับจำนวนสูงสุดที่ BigInteger สามารถแสดงนั้นสามารถได้มาจากขนาดอาร์เรย์สูงสุดที่มีอยู่ใน. net มีหัวข้อเกี่ยวกับอาร์เรย์อยู่ที่นี่: Finding หน่วยความจำเท่าใดฉันสามารถจัดสรรสำหรับอาร์เรย์ใน C #

สมมติว่าเรารู้ขนาดอาเรย์สูงสุดเราสามารถประมาณจำนวนสูงสุดซึ่ง BigInteger สามารถแสดง: (2 ^ 32) ^ max_array_size โดยที่:

  • 2 ^ 32 - จำนวนสูงสุดในเซลล์อาร์เรย์ (int)
  • max_array_size - ขนาดสูงสุดที่อนุญาตของอาร์เรย์ int ซึ่งถูก จำกัด ด้วยขนาดวัตถุ 2GB

ซึ่งจะให้ตัวเลขที่มีทศนิยม 600 ล้านหลัก

ขีด จำกัด ประสิทธิภาพ

สำหรับประสิทธิภาพ BigInteger ใช้อัลกอริทึม Karatsubaสำหรับการคูณและอัลกอริทึมเชิงเส้นสำหรับการเพิ่ม ความซับซ้อนในการคูณคือ3 * n ^ 1.585หมายความว่ามันจะขยายได้ค่อนข้างดีแม้สำหรับจำนวนมาก ( กราฟความซับซ้อน ) อย่างไรก็ตามคุณยังสามารถตีประสิทธิภาพได้ตามขนาด RAM และแคชตัวประมวลผล

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


นี่เป็นข้อมูลที่ยอดเยี่ยม แต่แหล่งที่ BigInteger ของคุณอาศัยอยู่ในอาร์เรย์นั้นอยู่ที่ไหน
Pacerier

ฉันเพิ่งขุดเป็นแหล่ง. net โดยใช้ dotPeek ดูเหมือนว่าหมายเลขจะถูกเก็บไว้ภายใน uint [] _data ของโครงสร้าง BigInteger
Valera Kolupaev

* อัปเดตด้วยคำตอบที่ละเอียดยิ่งขึ้น แต่ฉันไม่พบซอร์สโค้ด. net ใด ๆ ที่ฉันสามารถอ้างอิงได้ยกเว้นตัวอย่างโค้ดที่แยกส่วน
Valera Kolupaev

สำหรับฉันแล้วดูเหมือนว่ามีอัลกอริธึมการคูณแบบมาตรฐานใน. NET เนื่องจากสามารถหาได้จาก ILSpy:. NET BigInteger Multiplication
Ivan Kochurkin

1

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

แน่นอนว่าอัลกอริทึมมักจะช้าลงเมื่อตัวเลขมีขนาดใหญ่ขึ้น แต่ก็ไม่ช้าลงมากนัก

เมื่อคุณใช้ตัวเลขในช่วงหลักล้านคุณอาจต้องการคิดถึงวิธีแก้ปัญหาอื่น ๆ - เนื่องจากการคำนวณกับพวกมันช้าลงเช่นกัน


0

มีการใช้งานไม่กี่ครั้งในชุมชนวิทยาศาสตร์ (เช่นระยะห่างระหว่างกาแลกซี่จำนวนอะตอมในทุ่งหญ้าและอื่น ๆ )


เอ่อไม่หยาบคาย .. แต่คำตอบนี้เกี่ยวข้องกับคำถามอย่างไร
Pacerier

2
คำถามที่เขียนดูเหมือนว่าเขากำลังมองหาตัวอย่างในโลกแห่งความเป็นจริงว่าทำไมชนิดข้อมูลดังกล่าวจะต้องถูกสร้างขึ้น
Dave Wise

การใช้ถ้อยคำใหม่ที่ดีกว่าคือ "คือ BigInteger เหมาะสำหรับตัวเลขที่มีขนาดใหญ่ถึง 10 ^ 30" หรือไม่
Pacerier

สำหรับเรื่องนี้ฉันจะใช้ดีกว่าdoubleหรือfloat- คุณไม่มีความแม่นยำที่จำเป็นเลย
Paŭlo Ebermann

การใช้ถ้อยคำใหม่ที่ดีกว่าคือ "BigInteger เหมาะสำหรับตัวเลขที่มีขนาดใหญ่ถึง 10 ^ 30 เมื่อเราต้องการความแม่นยำ" หรือไม่
Pacerier

0

ตามคำตอบของไคลน์ไคลน์ BigNumbers ถูกเพิ่มเข้าไปใน. NET primarlily เพราะพวกเขาจำเป็นต้องใช้เป็นหน่วยการสร้างสำหรับอัลกอริทึมการเข้ารหัสที่ทันสมัยจำนวนมาก (ลายเซ็นดิจิตอลการเข้ารหัสคีย์สาธารณะ / ส่วนตัว ฯลฯ ) อัลกอริทึมการเข้ารหัสลับสมัยใหม่จำนวนมากเกี่ยวข้องกับการคำนวณค่าจำนวนเต็มที่มีขนาดสูงถึงหลายพันบิต เนื่องจากคลาส BigNumber อธิบายคลาสที่กำหนดไว้อย่างดีและมีประโยชน์พวกเขาตัดสินใจที่จะทำให้เป็นสาธารณะ (แทนที่จะทำให้เป็นรายละเอียดภายในของ API การเข้ารหัสลับ)


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