ประเภทจุดลอยตัวขนาดคงที่


92

ในส่วนหัวstdint.h(C99), boost / cstdint.hppและcstdint(C ++ 0x) จะมีประเภทint32_tอื่น ๆ

มีประเภทจุดลอยตัวขนาดคงที่ใกล้เคียงกันหรือไม่? บางอย่างเช่นfloat32_t?


4
ทำไมคุณถึงต้องการอะไรแบบนั้น?
AraK

41
คุณต้องการอะไรแบบนั้นเมื่อคุณมีโครงสร้างข้อมูลที่มีค่าทศนิยมและคุณต้องการทราบด้วยว่าขนาดของมันคือเท่าใด
ม็อบ

5
@mobrule: หากคุณต้องการทราบขนาดคุณต้องใช้ตัวsizeofดำเนินการ ประเภทเช่นนี้จะมีประโยชน์เมื่ออัลกอริทึมกำหนดให้เป็นขนาดเฉพาะที่ทราบ
Stephen Canon

6
@Stephen Canon - ใช่สำหรับเมื่อคุณต้องการรับประกันว่าขนาดเท่าไหร่ สมมติว่าอินสแตนซ์ของโครงสร้างข้อมูลของคุณจะพอดีกับ 64 บิตและสามารถส่งผ่านค่าไปยังไลบรารีภายนอกบางส่วนได้
ม็อบ

7
@StephenCanon พิจารณาไลบรารีอนุกรมข้ามแพลตฟอร์ม วิธีที่สามารถsizeofนำมาใช้ในการแก้ปัญหาของการอย่างต่อเนื่องและจัดสรร unmarshalling ประเภทลอยตัว?
Kyle Strand

คำตอบ:


48

ไม่มีสิ่งนี้อยู่ในมาตรฐาน C หรือ C ++ ในปัจจุบัน ในความเป็นจริงไม่มีแม้แต่การรับประกันว่าfloatจะเป็นรูปแบบทศนิยมแบบไบนารีเลย

คอมไพเลอร์บางตัวรับประกันว่าfloatประเภทนี้จะเป็นรูปแบบไบนารี IEEE-754 32 บิต บางคนไม่ทำ ในความเป็นจริงfloatนั้นเป็นประเภท IEEE-754 singleบนแพลตฟอร์มที่ไม่ได้ฝังส่วนใหญ่แม้ว่าจะมีคำเตือนทั่วไปเกี่ยวกับคอมไพเลอร์บางตัวที่ประเมินนิพจน์ในรูปแบบที่กว้างขึ้น

มีคณะทำงานหารือเกี่ยวกับการเพิ่มการผูกภาษา C สำหรับการแก้ไข IEEE-754 ปี 2008 ซึ่งอาจพิจารณาแนะนำให้เพิ่ม typedef ดังกล่าว หากสิ่งนี้ถูกเพิ่มลงใน C ฉันคาดว่ามาตรฐาน C ++ จะเป็นไปตาม ... ในที่สุด


3
ไม่ว่าจะเป็น IEEE-754 หรือไม่ก็ตามก็ยังไม่สามารถป้องกันปัญหาการพกพาได้
Mark B

1
@Pietro: การเปลี่ยนภาษาจะไม่ส่งผลกระทบต่อความเข้ากันได้ของฮาร์ดแวร์ แต่จะกีดกันฮาร์ดแวร์บางส่วนจากการปฏิบัติตามข้อกำหนดเท่านั้น การรับประกัน IEEE FP จะช่วยในการพกพาได้อย่างไร
Potatoswatter

1
@ Potatoswatter: จะสนับสนุนให้ผู้จำหน่ายฮาร์ดแวร์จัดหาโซลูชันที่สอดคล้องกัน หากส่วน a รองรับมาตรฐาน C โดยไม่จำเป็นต้องแฮ็กไลบรารี soft-float และส่วน b ไม่ได้นั่นเป็นข้อได้เปรียบทางการตลาดสำหรับส่วนก.
Stephen Canon

2
@ Potatoswatter: (เกือบ) ไม่มีใครสนใจเกี่ยวกับความเร็วของฮาร์ดแวร์ เราใส่ใจเกี่ยวกับความเร็วของซอฟต์แวร์ที่ทำงานบนฮาร์ดแวร์ ซอฟต์แวร์สามารถทำงานได้เร็วขึ้นหากฮาร์ดแวร์ที่ทำงานอยู่นั้นถูกยึดตามมาตรฐานและซอฟต์แวร์ไม่จำเป็นต้องตรวจจับและแก้ไขกรณีพิเศษที่แตกต่างกัน 15 กรณีขึ้นอยู่กับแพลตฟอร์มที่ทำงานอยู่
Stephen Canon

8
คุณจะพกพาได้ดีขึ้นบนโลกได้อย่างไรโดยการป้องกันไม่ให้โค้ดของคุณรวบรวมในสถาปัตยกรรมเฉพาะกลุ่ม ไม่ว่าคุณจะพึ่งพาการลอยตัวเป็น IEEE ซึ่งในกรณีนี้โค้ดของคุณจะทำงานบนการใช้งานที่สอดคล้องกับ IEEE ทุกครั้งและไม่มีอะไรอื่นหรือคุณไม่ทำในกรณีนี้โค้ดของคุณจะทำงานบนระบบที่หลากหลายกว่า ถ้า c ++ รับประกัน IEEE ปฏิบัติตามรหัสของคุณจะไม่ได้รับความน่าอัศจรรย์แบบพกพามากขึ้นคุณต้องการเพียงแค่ออกกฎว่ามันอาจจะเคยทำงานบนสถาปัตยกรรมเหล่านั้นไม่สอดคล้อง ตรรกะของคุณถอยหลังอย่างสมบูรณ์
jalf

30

หากคุณต้องการทราบว่าคุณfloatเป็น IEEE ชนิด 32 std::numeric_limits<float>::is_iec559บิตตรวจสอบ เป็นค่าคงที่เวลาคอมไพล์ไม่ใช่ฟังก์ชัน

หากคุณต้องการที่จะเป็นกระสุนมากขึ้นนอกจากนี้ยังมีการตรวจสอบstd::numeric_limits<float>::digitsเพื่อให้แน่ใจว่าพวกเขาจะไม่ลอบใช้มาตรฐาน IEEE floatแม่นยำสองสำหรับ มันควรจะเป็น 24

เมื่อพูดถึงlong doubleเรื่องนี้สิ่งสำคัญกว่าในการตรวจสอบdigitsเนื่องจากมีรูปแบบ IEEE สองสามรูปแบบซึ่งอาจเป็นได้: 128 บิต (หลัก = 113) หรือ 80 บิต (หลัก = 64)

มันจะไม่เป็นประโยชน์ที่จะมีfloat32_tเช่นนี้เพราะโดยปกติคุณต้องการใช้ฮาร์ดแวร์ทศนิยมถ้ามีและไม่ต้องถอยกลับไปใช้งานซอฟต์แวร์


long doubleรูปแบบใน OS X (ทั้งแบบ 32 บิตและ 64 บิต Intel) เป็นว่ารูปแบบการขยาย IEEE-754 คู่เก็บไว้ในการสั่งซื้อน้อย endian ไม่มีอะไรขี้ขลาดเลย ไบต์ 0-7 ถือฟิลด์สำคัญและไบต์ 8 และ 9 ถือฟิลด์เลขชี้กำลังและเครื่องหมาย
Stephen Canon

@ สตีเฟ่น: นั่นเป็นข่าวดี: v) นั่นเห็นด้วยกับตัวเลขที่ฉันโพสต์หรือไม่?
Potatoswatter

1
โปรดจำไว้ว่าคู่ขยาย (ไม่เหมือนคนอื่น ๆ 754 รูปแบบ) มีอย่างชัดเจนบิตซิกชั้นนำเพื่อให้มีซิกของ5.0L a000000000000000ตัวแทนที่เป็นกลางของมันคือ 2 และคู่อคติตัวแทนขยาย3fffเพื่อให้ตัวแทนลำเอียงสำหรับ 5.0L 4001เป็น รูปแบบไบต์ที่แท้จริงเมื่อจัดเก็บในลำดับที่น้อยที่สุดคือ00 00 00 00 00 00 00 a0 01 40และถ้าคุณมองว่าเป็นจำนวนเต็ม 64 บิตแบบ endian ตัวน้อยสองตัวคุณจะเห็นสิ่งที่คุณสังเกตได้
Stephen Canon

(*) ขยายเป็นสองเท่าตามที่ Intel ใช้ในฮาร์ดแวร์นั่นคือ รูปแบบการขยายสองครั้งไม่ได้ถูกตรึงไว้ในรูปแบบพื้นฐานอีกสองรูปแบบของ IEEE-754 (1985)
Stephen Canon

@Stephen: ฉันค่อนข้างมั่นใจว่า4001ใน little-endian คือ01 40 00 00 ...ถ้าไม่มีอะไรอื่นไบต์ที่มีนัยสำคัญน้อยที่สุดมาก่อน ฉันคาดว่าลำดับa0 01 40จะปรากฏที่ใดที่หนึ่งในตัวเลข (หากพวกเขาทำการหมุนเวียนเท่านั้น) แต่ฉันไม่คิดว่าคุณอธิบายสาเหตุa0และ01 40อยู่ในช่วงครึ่งปีที่แยกจากกันโดยสิ้นเชิง
Potatoswatter

18

หากคุณคิดว่ามี typedefs เช่น float32_t และ float64_t ไม่สามารถใช้งานได้ไม่ว่าด้วยเหตุผลใดก็ตามคุณต้องคุ้นเคยกับระบบปฏิบัติการคอมไพเลอร์ที่คุ้นเคยมากเกินไปจนไม่สามารถมองออกไปนอกรังเล็ก ๆ ของคุณได้

มีฮาร์ดแวร์ที่รันการดำเนินการจุดลอยตัว IEEE 32 บิตและอื่น ๆ ที่ทำ 64 บิต บางครั้งระบบดังกล่าวยังต้องคุยกับอีกฝ่ายซึ่งในกรณีนี้สิ่งสำคัญอย่างยิ่งที่จะต้องทราบว่าคู่คือ 32 บิตหรือ 64 บิตในแต่ละแพลตฟอร์ม หากแพลตฟอร์ม 32 บิตต้องทำการคำนวณมากเกินไปบนพื้นฐานของค่า 64 บิตจากค่าอื่นเราอาจต้องการแคสต์ให้มีความแม่นยำต่ำลงโดยขึ้นอยู่กับข้อกำหนดด้านเวลาและความเร็ว

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


"โดยส่วนตัวแล้วฉันรู้สึกไม่สบายใจที่จะใช้โฟลตและเพิ่มเป็นสองเท่าเว้นแต่ฉันจะรู้ว่ามันอยู่บนแพลตฟรอมของฉันกี่บิตยิ่งไปกว่านั้นถ้าฉันจะถ่ายโอนสิ่งเหล่านี้ไปยังแพลตฟอร์มอื่นผ่านช่องทางการสื่อสารบางช่อง" - คุณหมายถึงคุณใช้รูปแบบไฟล์ข้อความ? ด้วยสิ่งเหล่านี้มีข้อเสียของขนาดไฟล์: 32 float ต้องการ 4 ไบต์; สิ่งเหล่านี้ในรูปแบบข้อความสามารถแทนตัวเลขสี่หลักเท่านั้น ...
Pietro

3

ขณะนี้มีข้อเสนอให้เพิ่มประเภทต่อไปนี้ลงในภาษา:

decimal32
decimal64
decimal128

#include <decimal>ซึ่งอาจจะเป็นวันหนึ่งที่สามารถเข้าถึงได้ผ่านทาง

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3871.html


3
จริงอยู่ประเภททศนิยมไม่ใช่ประเภททศนิยมของ IEEE 754
Mike DeSimone

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