लुआ के स्रोत कोड को पढ़ते समय , मैंने देखा कि लुआ 32-बिट के macroचक्कर लगाने के लिए एक का उपयोग करता है । मैंने निकाला , और यह इस तरह दिखता है:doubleintmacro
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 रूप में परिभाषित किया गया है , छोटे एंडियन के लिए, बड़े एंडियन के लिए। लुआ सावधानी से धीरज धरता है। पूर्णांक प्रकार के लिए खड़ा है, जैसे या ।01tintunsigned int
मैंने थोड़ा शोध किया और इसका एक सरल प्रारूप है macroजो समान विचार का उपयोग करता है:
#define double2int(i, d) \
{double t = ((d) + 6755399441055744.0); i = *((int *)(&t));}
या सी ++ में - शैली:
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-बिट पूर्णांक इस जादू की संख्या में जोड़ा जाता है, ठीक है, मैं यहाँ से खो गया हूं। यह ट्रिक कैसे काम करती है?
पुनश्च: यह Lua स्रोत कोड, Llimits.h में है ।
अद्यतन :
- जैसा कि @Mysticial बताते हैं, यह विधि केवल 32-बिट तक ही सीमित नहीं है
int, इसे 64-बिटintतक भी विस्तारित किया जा सकता है, जब तक कि यह संख्या 2 ^ 52 की सीमा में है। (macroकुछ संशोधन की जरूरत है।) - कुछ सामग्रियों का कहना है कि इस विधि का उपयोग Direct3D में नहीं किया जा सकता है ।
जब Microsoft असेंबलर के साथ x86 के लिए काम कर रहा है, तो इसमें और भी तेज़ी से
macroलिखा गया हैassembly(यह लुआ स्रोत से भी निकाला गया है):#define double2int(i,n) __asm {__asm fld n __asm fistp i}एकल सटीक संख्या के लिए एक समान मैजिक नंबर है:
1.5 * 2 ^23
ftoi। लेकिन अगर आप एसएसई की बात कर रहे हैं, तो सिर्फ एक निर्देश का उपयोग क्यों न करें CVTTSD2SI?
double -> int64वास्तव में 2^52सीमा के भीतर हैं । फ्लोटिंग-पॉइंट एफएफटी का उपयोग करते हुए पूर्णांक आक्षेप करते समय ये विशेष रूप से सामान्य हैं।
