อะไรคือจำนวนเต็ม "ไม่ลอย" ที่ใหญ่ที่สุดที่สามารถเก็บไว้ใน IEEE 754 double type โดยไม่สูญเสียความแม่นยำ
อะไรคือจำนวนเต็ม "ไม่ลอย" ที่ใหญ่ที่สุดที่สามารถเก็บไว้ใน IEEE 754 double type โดยไม่สูญเสียความแม่นยำ
คำตอบ:
จำนวนเต็มที่ใหญ่ที่สุด / ใหญ่ที่สุดที่สามารถเก็บไว้ในคู่โดยไม่สูญเสียความแม่นยำเท่ากับค่าที่ใหญ่ที่สุดที่เป็นไปได้ของคู่ นั่นคือDBL_MAX
หรือประมาณ 1.8 × 10 308 (ถ้า double ของคุณเป็น IEEE 754 64- บิตสองเท่า) มันเป็นจำนวนเต็ม มันแสดงว่า คุณต้องการอะไรอีก
ต่อไปถามสิ่งที่เป็นจำนวนเต็มมากที่สุดเช่นนั้นและจำนวนเต็มขนาดเล็กทั้งหมดสามารถเก็บไว้ใน IEEE 64- บิตคู่โดยไม่สูญเสียความแม่นยำ IEEE 64- บิตสองเท่ามี 52 mantissa ดังนั้นฉันคิดว่ามันคือ 2 53 :
หรือวิธีอื่นในการมองดู: เมื่ออคติได้ถูกลบล้างเลขชี้กำลังและไม่สนใจเครื่องหมายบิตที่ไม่เกี่ยวข้องกับคำถามค่าที่จัดเก็บโดย double จะมีค่าเป็น 2 และบวกด้วยจำนวนเต็ม 52 บิตคูณด้วย 2 ตัวแทน - 52 ดังนั้นด้วยตัวแทน 52 คุณสามารถจัดเก็บค่าทั้งหมดจาก 2 52ผ่านไป 2 53 - 1 แล้วกับตัวแทน 53 จำนวนต่อไปที่คุณสามารถจัดเก็บหลังจาก 2 53 2 53 + 1 × 2 53 - 52 ดังนั้นการสูญเสียความแม่นยำครั้งแรกเกิดขึ้นกับ 2 53 + 1
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
double dbl = 1; while (dbl + 1 != dbl) dbl *= 2; while (dbl == --dbl);
ให้ผลลัพธ์เดียวกัน
while (dbl == --dbl)
จะวนซ้ำไปตลอดกาลหรือไม่ :) (ในกรณีนี้ไม่ใช่ทั้งหมดเนื่องจากเป็น 2 ^ N) คุณจะต้องเข้าหามันจากด้านล่าง มันจะส่งผลให้ผลลัพธ์ที่คาดหวังน้อยลงหนึ่งรายการ (เนื่องจากการตรวจสอบครั้งเดียวในขณะที่ลูปลดลง dbl) และขึ้นอยู่กับคำสั่งของการดำเนินการหากการลดลงทำก่อนหรือหลังการประเมินด้านซ้าย (ซึ่งไม่ได้กำหนดเท่าที่ฉันรู้) ถ้ามันเป็นอดีตมันจะเป็นจริงและวนซ้ำไปตลอดกาล
while (dbl + 1 != dbl) dbl++;
ในการที่dbl + 1 != dbl
อาจประเมินโดยใช้long double
คณิตศาสตร์ - FLT_EVAL_METHOD == 2
พิจารณา นี่อาจจบลงด้วยการวนซ้ำไม่สิ้นสุด
Wikipedia มีสิ่งนี้เพื่อพูดในบริบทเดียวกันโดยมีลิงก์ไปยังIEEE 754 :
บนระบบคอมพิวเตอร์ทั่วไปเลขฐานสอง 'ความแม่นยำสองเท่า (64 บิต) มีค่าสัมประสิทธิ์ 53 บิต (หนึ่งในนั้นก็บอกเป็นนัย) เลขชี้กำลัง 11 บิตและบิตหนึ่งสัญญาณ
2 ^ 53 มีค่าเกิน 9 * 10 ^ 15
จำนวนเต็มที่มากที่สุดที่สามารถแสดงใน IEEE 754 double (64- บิต) จะเหมือนกับค่าที่มากที่สุดที่ชนิดสามารถเป็นตัวแทนได้เนื่องจากค่านั้นเป็นจำนวนเต็มเอง
นี่คือตัวแทน0x7FEFFFFFFFFFFFFF
ซึ่งประกอบด้วย:
0x7FE
(2046 ซึ่งหมายถึง 1,023 หลังจากลบอคติ) แทนที่จะเป็น0x7FF
(2047 ซึ่งหมายถึง a NaN
หรือไม่มีที่สิ้นสุด)0xFFFFFFFFFFFFF
ซึ่งเป็น 52 บิตทั้งหมด 1ในเลขฐานสองค่าเป็นค่านัย 1 ตามด้วยอีก 52 อันจากแมนทิสซาจากนั้นก็เป็นศูนย์ 971 (1023 - 52 = 971) จากเลขชี้กำลัง
ค่าทศนิยมที่แน่นอนคือ:
179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368
นี้จะอยู่ที่ประมาณ 1.8 x 10 308
คุณต้องดูขนาดของมันตาสา หมายเลขจุดลอยตัว IEEE 754 64 บิต (ซึ่งมี 52 บิตบวกด้วยนัย 1) สามารถแทนจำนวนเต็มด้วยค่าสัมบูรณ์น้อยกว่าหรือเท่ากับ 2 ^ 53
1.7976931348623157 × 10 ^ 308
http://en.wikipedia.org/wiki/Double_precision_floating-point_format
DECIMAL_DIG
จาก<float.h>
ควรให้อย่างน้อยประมาณที่เหมาะสมของการที่ เนื่องจากข้อเสนอว่าด้วยตัวเลขทศนิยมและก็เก็บไว้จริงๆในไบนารีคุณอาจจะสามารถจัดเก็บบางสิ่งบางอย่างเล็ก ๆ น้อย ๆที่มีขนาดใหญ่โดยไม่สูญเสียความแม่นยำ แต่ว่าเท่าไหร่เป็นเรื่องยากที่จะบอกว่า ฉันคิดว่าคุณควรจะสามารถที่จะคิดออกจากFLT_RADIX
และDBL_MANT_DIG
แต่ผมไม่แน่ใจว่าผมจะสมบูรณ์ไว้วางใจผล
double
ตรงกับประเภท IEEE ที่เฉพาะเจาะจงโดยตรง แต่ไม่จำเป็นและเมื่อคำตอบนี้ถูกเขียนคำถามไม่ได้พูดถึงประเภท IEEE เฉพาะ