เมื่ออ่านLua ของรหัสที่มาผมสังเกตเห็นว่า Lua ใช้macro
ในการออกรอบdouble
กับ int
32 ฉันดึงข้อมูลmacro
และดูเหมือนว่า:
union i_cast {double d; int i[2]};
#define double2int(i, d, t) \
{volatile union i_cast u; u.d = (d) + 6755399441055744.0; \
(i) = (t)u.i[ENDIANLOC];}
ที่นี่ENDIANLOC
ถูกกำหนดให้เป็นendianness , 0
สำหรับ endian เล็ก ๆ น้อย ๆ1
สำหรับ endian ใหญ่ Lua จัดการกับ endianness อย่างระมัดระวัง t
ย่อมาจากชนิดจำนวนเต็มเช่นหรือint
unsigned int
ฉันทำวิจัยเล็กน้อยและมีรูปแบบที่ง่ายกว่าmacro
ซึ่งใช้ความคิดเดียวกัน:
#define double2int(i, d) \
{double t = ((d) + 6755399441055744.0); i = *((int *)(&t));}
หรือในสไตล์ C ++:
inline int double2int(double d)
{
d += 6755399441055744.0;
return reinterpret_cast<int&>(d);
}
เคล็ดลับนี้สามารถทำงานกับเครื่องใด ๆ ที่ใช้IEEE 754 (ซึ่งหมายถึงทุกเครื่องในปัจจุบัน) มันทำงานสำหรับตัวเลขทั้งบวกและลบและการปัดเศษตามกฎของธนาคาร (สิ่งนี้ไม่น่าแปลกใจเนื่องจากเป็นไปตาม IEEE 754)
ฉันเขียนโปรแกรมเล็ก ๆ เพื่อทดสอบ:
int main()
{
double d = -12345678.9;
int i;
double2int(i, d)
printf("%d\n", i);
return 0;
}
และมันจะออกผลลัพธ์ -12345679 ตามที่คาดไว้
ฉันต้องการทราบรายละเอียดวิธีการmacro
ทำงานที่ซับซ้อนนี้ จำนวนมายากล6755399441055744.0
เป็นจริง2^51 + 2^52
หรือ1.5 * 2^52
และในไบนารีสามารถแสดงเป็น1.5
1.1
เมื่อเลขจำนวนเต็ม 32 บิตใด ๆ ถูกเพิ่มเข้าไปในจำนวนเวทย์มนตร์นี้ก็หายไปจากที่นี่ เคล็ดลับนี้ทำงานอย่างไร
PS: นี่คือในรหัสที่มา Lua, Llimits.h
อัปเดต :
- เนื่องจาก @Mysticial ชี้ให้เห็นวิธีการนี้ไม่ได้ จำกัด อยู่ที่ 32 บิต
int
แต่ก็สามารถขยายได้ถึง 64 บิตint
ตราบใดที่ตัวเลขนั้นอยู่ในช่วง 2 ^ 52 (macro
ความต้องการการปรับเปลี่ยนบางอย่าง) - วัสดุบางอย่างบอกว่าวิธีนี้ไม่สามารถใช้ในDirect3Dได้
เมื่อทำงานกับ Microsoft Assembler สำหรับ x86 จะมีการ
macro
เขียนที่เร็วขึ้นassembly
(สิ่งนี้ยังแยกมาจากแหล่ง Lua):#define double2int(i,n) __asm {__asm fld n __asm fistp i}
มีหมายเลขเวทย์มนตร์ที่คล้ายกันสำหรับหมายเลขความแม่นยำเดียว:
1.5 * 2 ^23
ftoi
ฉันสามารถดูได้ว่ามันจะเร็วกว่า แต่ถ้าคุณกำลังพูดถึง SSE ทำไมไม่ใช้แค่คำสั่งเดียวCVTTSD2SI
?
double -> int64
แน่นอนอยู่ใน2^52
ช่วง สิ่งเหล่านี้เป็นเรื่องปกติโดยเฉพาะอย่างยิ่งเมื่อดำเนินการโน้มน้าวใจจำนวนเต็มโดยใช้ FFT ที่เป็นทศนิยม