จำนวนเต็มที่ใหญ่ที่สุดที่สามารถเก็บไว้ในสองครั้ง


คำตอบ:


506

จำนวนเต็มที่ใหญ่ที่สุด / ใหญ่ที่สุดที่สามารถเก็บไว้ในคู่โดยไม่สูญเสียความแม่นยำเท่ากับค่าที่ใหญ่ที่สุดที่เป็นไปได้ของคู่ นั่นคือDBL_MAXหรือประมาณ 1.8 × 10 308 (ถ้า double ของคุณเป็น IEEE 754 64- บิตสองเท่า) มันเป็นจำนวนเต็ม มันแสดงว่า คุณต้องการอะไรอีก

ต่อไปถามสิ่งที่เป็นจำนวนเต็มมากที่สุดเช่นนั้นและจำนวนเต็มขนาดเล็กทั้งหมดสามารถเก็บไว้ใน IEEE 64- บิตคู่โดยไม่สูญเสียความแม่นยำ IEEE 64- บิตสองเท่ามี 52 mantissa ดังนั้นฉันคิดว่ามันคือ 2 53 :

  • 2 53 + 1 ไม่สามารถจัดเก็บได้เนื่องจาก 1 ที่จุดเริ่มต้นและ 1 ที่จุดสิ้นสุดมีค่าศูนย์มากเกินไป
  • สิ่งใดที่น้อยกว่า 2 53สามารถจัดเก็บได้โดยมี 52 บิตเก็บไว้ในแมนทิสซาอย่างชัดเจน
  • 2 53สามารถจัดเก็บได้อย่างชัดเจนเนื่องจากมันเป็นพลังงานขนาดเล็กที่ 2

หรือวิธีอื่นในการมองดู: เมื่ออคติได้ถูกลบล้างเลขชี้กำลังและไม่สนใจเครื่องหมายบิตที่ไม่เกี่ยวข้องกับคำถามค่าที่จัดเก็บโดย double จะมีค่าเป็น 2 และบวกด้วยจำนวนเต็ม 52 บิตคูณด้วย 2 ตัวแทน - 52 ดังนั้นด้วยตัวแทน 52 คุณสามารถจัดเก็บค่าทั้งหมดจาก 2 52ผ่านไป 2 53  - 1 แล้วกับตัวแทน 53 จำนวนต่อไปที่คุณสามารถจัดเก็บหลังจาก 2 53 2 53 + 1 × 2 53 - 52 ดังนั้นการสูญเสียความแม่นยำครั้งแรกเกิดขึ้นกับ 2 53 + 1


126
+1 ดีมากสังเกตว่าคำถามไม่ได้หมายความว่าผู้ถามตั้งใจจะให้อะไรและให้คำตอบทั้งคู่ ("ถูกต้องทางเทคนิค" และ "คาดว่าจะได้")
Pascal Cuoq

62
หรือ "ล้อเล่น" และ "พยายามที่จะช่วย" เท่าที่ฉันมีแนวโน้มที่จะเรียกพวกเขา :-)
สตีฟเจสซอพ

8
ฉันคำนับกับ Tony the Pony และไม่มีอื่น ๆ
Steve Jessop

11
คุณไม่ได้หมายถึง "จำนวนเต็มเล็กทั้งหมด" คุณหมายถึงจำนวนเต็มทั้งหมดที่เท่ากันหรือน้อยกว่า เนื่องจากมีจำนวนเต็มลบด้านล่างต่ำกว่า 2 ^ 53 จำนวนมากและไม่สามารถแสดงเป็นคู่ได้อย่างแม่นยำ
ภาคใต้

13
ฉันหมายถึงขนาดเล็กลงและนั่นคือสิ่งที่ฉันหมายถึงเมื่อพูดว่า :-) น้อยกว่า -1,000,000 น้อยกว่า 1 แต่ไม่เล็ก
Steve Jessop

77

9007199254740992 (นั่นคือ 9,007,199,254,740,992) โดยไม่มีการรับประกัน :)

โปรแกรม

#include <math.h>
#include <stdio.h>

int main(void) {
  double dbl = 0; /* I started with 9007199254000000, a little less than 2^53 */
  while (dbl + 1 != dbl) dbl++;
  printf("%.0f\n", dbl - 1);
  printf("%.0f\n", dbl);
  printf("%.0f\n", dbl + 1);
  return 0;
}

ผลลัพธ์

9007199254740991
9007199254740992
9007199254740992

7
สมมติว่ามันจะ 'ปิด' แต่น้อยกว่า 2 ^ N จากนั้นการทดสอบที่เร็วกว่าจะdouble dbl = 1; while (dbl + 1 != dbl) dbl *= 2; while (dbl == --dbl);ให้ผลลัพธ์เดียวกัน
Seph

4
@Seph อะไร ... ไม่มี? while (dbl == --dbl)จะวนซ้ำไปตลอดกาลหรือไม่ :) (ในกรณีนี้ไม่ใช่ทั้งหมดเนื่องจากเป็น 2 ^ N) คุณจะต้องเข้าหามันจากด้านล่าง มันจะส่งผลให้ผลลัพธ์ที่คาดหวังน้อยลงหนึ่งรายการ (เนื่องจากการตรวจสอบครั้งเดียวในขณะที่ลูปลดลง dbl) และขึ้นอยู่กับคำสั่งของการดำเนินการหากการลดลงทำก่อนหรือหลังการประเมินด้านซ้าย (ซึ่งไม่ได้กำหนดเท่าที่ฉันรู้) ถ้ามันเป็นอดีตมันจะเป็นจริงและวนซ้ำไปตลอดกาล
falstro

10
อาจระบุว่า 2 ^ 53 = 9,007,199,254,740,992 แห่ง
Xonatron

1
เป็นการยากที่จะโต้แย้งเรื่องนี้! การทดสอบที่ดี
MattM

จุดอ่อนที่จะใช้while (dbl + 1 != dbl) dbl++;ในการที่dbl + 1 != dblอาจประเมินโดยใช้long doubleคณิตศาสตร์ - FLT_EVAL_METHOD == 2พิจารณา นี่อาจจบลงด้วยการวนซ้ำไม่สิ้นสุด
chux - Reinstate Monica

25

Wikipedia มีสิ่งนี้เพื่อพูดในบริบทเดียวกันโดยมีลิงก์ไปยังIEEE 754 :

บนระบบคอมพิวเตอร์ทั่วไปเลขฐานสอง 'ความแม่นยำสองเท่า (64 บิต) มีค่าสัมประสิทธิ์ 53 บิต (หนึ่งในนั้นก็บอกเป็นนัย) เลขชี้กำลัง 11 บิตและบิตหนึ่งสัญญาณ

2 ^ 53 มีค่าเกิน 9 * 10 ^ 15


@ Steve Jessop มากหรือน้อยนั่นคือสิ่งที่ฉันกำลังพูด ฉันได้พบกับระบบฮาร์ดแวร์ที่ไม่มี FPU ที่ยังต้องเป็นไปตามมาตรฐาน IEEE ดังนั้นสิ่งที่ "ระบบทั่วไป" ไม่ได้ช่วยฉันจริงๆถ้าฉันกลับมาที่นี่อีก 8 เดือนต่อมาและต้องการข้อมูลเดียวกันสำหรับ ไมโครคอนโทรลเลอร์ที่ใช้ 68K ของฉัน (สมมติว่ามันไม่มี FPU ... ฉันจำไม่ได้)
San Jacinto

14
@San Jacinto - "นี่ไร้ประโยชน์" เป็นความเมตตาอย่างไม่เหมาะสม คำตอบนั้นค่อนข้างมีประโยชน์ แต่ก็ไม่ได้มีประโยชน์อย่างที่ควรจะเป็นหากรวมความคิดเห็นที่ว่าระบบคอมพิวเตอร์ทั่วไปใช้การตอบโต้ IEEE 754 อย่างแน่นอน
สตีเฟ่นซีเหล็ก

@ สตีเฟ่นซีเหล็กจริง ๆ แล้วคุณถูกต้อง ภายใต้สถานการณ์ของฉันกลับมาที่นี่อีกครั้งในภายหลังและมองหา IEEE max มันเป็นสิ่งที่คลุมเครืออย่างไม่น่าเชื่อว่า 'ระบบทั่วไป' คืออะไร แต่ก็ยังมีข้อดีอยู่ในคำตอบนอกเหนือจากการร้องเรียนนี้
San Jacinto

20

จำนวนเต็มที่มากที่สุดที่สามารถแสดงใน IEEE 754 double (64- บิต) จะเหมือนกับค่าที่มากที่สุดที่ชนิดสามารถเป็นตัวแทนได้เนื่องจากค่านั้นเป็นจำนวนเต็มเอง

นี่คือตัวแทน0x7FEFFFFFFFFFFFFFซึ่งประกอบด้วย:

  • เครื่องหมายบิต 0 (บวก) มากกว่า 1 (ลบ)
  • เลขชี้กำลังสูงสุด0x7FE(2046 ซึ่งหมายถึง 1,023 หลังจากลบอคติ) แทนที่จะเป็น0x7FF(2047 ซึ่งหมายถึง a NaNหรือไม่มีที่สิ้นสุด)
  • mantissa สูงสุด0xFFFFFFFFFFFFFซึ่งเป็น 52 บิตทั้งหมด 1

ในเลขฐานสองค่าเป็นค่านัย 1 ตามด้วยอีก 52 อันจากแมนทิสซาจากนั้นก็เป็นศูนย์ 971 (1023 - 52 = 971) จากเลขชี้กำลัง

ค่าทศนิยมที่แน่นอนคือ:

179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368

นี้จะอยู่ที่ประมาณ 1.8 x 10 308


แล้วค่าที่ใหญ่ที่สุดที่มันสามารถแทนด้วยค่าทั้งหมดระหว่างมันและไม่มีอะไรสามารถแทนได้อย่างต่อเนื่อง
Aaron Franke

@AaronFranke คำถามไม่ได้ถามเกี่ยวกับการเป็นตัวแทนที่ต่อเนื่องกัน แต่คำตอบสำหรับคำถามที่แตกต่างนั้นได้รวมอยู่ในคำตอบอื่น ๆ ส่วนใหญ่ที่นี่หรือแม้แต่ได้รับอย่างผิด ๆ เป็นคำตอบที่แท้จริง มันคือ2⁵³ (2 ต่อกำลัง 53)
Simon Biber

8

คุณต้องดูขนาดของมันตาสา หมายเลขจุดลอยตัว IEEE 754 64 บิต (ซึ่งมี 52 บิตบวกด้วยนัย 1) สามารถแทนจำนวนเต็มด้วยค่าสัมบูรณ์น้อยกว่าหรือเท่ากับ 2 ^ 53


8
มันว่าสามารถเป็นตัวแทนของ 2 ^ 53, เกินไป :-)
สตีฟเจสซอพ

6

2
คำตอบนี้จะดีกว่ามากกับการอ้างอิง
San Jacinto

2
@ คาร์ลดีถ้าจำนวนเต็มมีศูนย์เหลืออยู่ทางซ้ายแสดงว่าเก็บไว้อย่างแม่นยำ
Wilhelm

4
@ all downvoters: 1.7976931348623157 × 10 ^ 308 เป็นจำนวนเต็มที่แน่นอน คุณทุกคนต้องเข้าร่วมชั้นเรียนคณิตศาสตร์แก้ไขหรืออะไร?
Dan Molding

6
เราลงไปที่ความหมายที่นี่ในการสนทนาของคำตอบจมอย่างสิ้นหวังนี้ จริงตัวเลขนั้นสามารถแทนได้อย่างถูกต้องและตรงตามตัวอักษรของคำถาม แต่เราทุกคนรู้ว่ามันเป็นเกาะเล็ก ๆ แห่งความแน่นอนในมหาสมุทรที่ใกล้ถึงจุดจบและพวกเราส่วนใหญ่แก้ไขคำถามอย่างถูกต้องเพื่อหมายถึง อามันช่างวิเศษจริงๆที่ CompSci เป็นวิทยาศาสตร์ที่แน่นอนเหรอ? :)
Carl Smotricz

2
@DanMoulding 1.7976931348623157 × 10 ^ 308 เป็นจำนวนเต็มแน่นอน แต่ฉันค่อนข้างมั่นใจว่าจำนวนเต็มนี้ไม่สามารถจัดเก็บเป็นคู่ได้อย่างแน่นอน
Pascal Cuoq

2

DECIMAL_DIGจาก<float.h>ควรให้อย่างน้อยประมาณที่เหมาะสมของการที่ เนื่องจากข้อเสนอว่าด้วยตัวเลขทศนิยมและก็เก็บไว้จริงๆในไบนารีคุณอาจจะสามารถจัดเก็บบางสิ่งบางอย่างเล็ก ๆ น้อย ๆที่มีขนาดใหญ่โดยไม่สูญเสียความแม่นยำ แต่ว่าเท่าไหร่เป็นเรื่องยากที่จะบอกว่า ฉันคิดว่าคุณควรจะสามารถที่จะคิดออกจากFLT_RADIXและDBL_MANT_DIGแต่ผมไม่แน่ใจว่าผมจะสมบูรณ์ไว้วางใจผล


สิ่งนี้ไม่ได้ให้คำตอบสำหรับคำถาม หากต้องการวิจารณ์หรือขอคำชี้แจงจากผู้แต่งโปรดแสดงความคิดเห็นใต้โพสต์ของพวกเขา
MichaelChirico

@MichaelChirico: นี่ตอบคำถามที่เขาตั้งใจจะถามเพราะมันมีอยู่เมื่อเขียนคำตอบ หากต้องการดูประวัติการแก้ไขของคำถามให้คลิกลิงก์ "แก้ไขเมื่อวันที่ 19 มิถุนายน '14 เวลา 11:40" ที่ด้านล่างของคำถาม
Jerry Coffin

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

1
@MichaelChirico: พวกเขาอาจมี - คุณอยู่ไกลจากคนเดียวที่ไม่รู้เรื่อง; สิ่งที่ทำให้คุณแปลกคือคุณรู้ตัวว่าไม่รู้ตัว คำตอบส่วนใหญ่ว่าเสียงที่เชื่อถือได้เกี่ยวกับความแม่นยำของตัวเลขจำนวนจุดลอยตัวใน C นั้นเข้าใจผิด ตัวอย่างเช่นส่วนใหญ่ (ส่วนใหญ่) ของพวกเขาข้างต้นขึ้นอยู่กับข้อสันนิษฐานเท็จที่doubleตรงกับประเภท IEEE ที่เฉพาะเจาะจงโดยตรง แต่ไม่จำเป็นและเมื่อคำตอบนี้ถูกเขียนคำถามไม่ได้พูดถึงประเภท IEEE เฉพาะ
Jerry Coffin

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