सबसे पहले आप अनियंत्रित संदर्भ का उपयोग कर रहे हैं जो कि एक कंपाइलर के लिए एक निर्देश है जो आपको एक डेवलपर के रूप में सुनिश्चित करता है, कि परिणाम ओवरफ्लो नहीं होगा और आप कोई संकलन त्रुटि नहीं देखना चाहेंगे। आपके परिदृश्य में आप वास्तव में उद्देश्य से अधिक प्रकार के हैं और तीन अलग-अलग कंपाइलरों में लगातार व्यवहार की अपेक्षा कर रहे हैं, जिनमें से एक रोसेलिन और .NET कोर की तुलना में इतिहास में संभवतः सबसे पिछड़ा संगत है जो नए हैं।
दूसरी बात यह है कि आप अंतर्निहित और स्पष्ट रूपांतरणों का मिश्रण कर रहे हैं। मैं रोज़लिन कंपाइलर के बारे में निश्चित नहीं हूं, लेकिन निश्चित रूप से .NET फ्रेमवर्क और .NET कोर कंपाइलर्स उन ऑपरेशनों के लिए अलग-अलग अनुकूलन का उपयोग कर सकते हैं।
यहां समस्या यह है कि आपके कोड की पहली पंक्ति केवल फ्लोटिंग पॉइंट वैल्यू / प्रकार का उपयोग करती है, लेकिन दूसरी लाइन फ्लोटिंग पॉइंट वैल्यू / टाइप और इंटीग्रल वैल्यू / टाइप का संयोजन है।
यदि आप पूर्णांक फ़्लोटिंग पॉइंट टाइप बनाते हैं तो सीधे (7> 7.0) आप तीनों संकलित स्रोतों के लिए एक ही परिणाम प्राप्त करेंगे।
using System;
public class Program
{
const float scale = 64 * 1024;
public static void Main()
{
Console.WriteLine(unchecked((uint)(ulong)(1.2 * scale * scale + 1.5 * scale))); // 859091763
Console.WriteLine(unchecked((uint)(ulong)(scale * scale + 7.0))); // 7
}
}
इसलिए, मैं इसके विपरीत कहूंगा कि V0ldek ने जो जवाब दिया और वह यह है कि "द बग (यदि यह वास्तव में एक बग है) रोसेलिन और .NET कोर कंपाइलर्स में सबसे अधिक संभावना है"।
यह मानने का एक और कारण यह है कि पहले अनियंत्रित संगणना के परिणाम सभी के लिए समान होते हैं और यह मान है कि अधिकतम UInt32
प्रकार का अधिकतम मान होता है ।
Console.WriteLine(unchecked((uint)(ulong)(1.2 * scale * scale + 1.5 * scale) - UInt32.MaxValue - 1)); // 859091763
माइनस एक वहाँ है क्योंकि हम शून्य से शुरू करते हैं जो मूल्य है जो खुद को घटाना मुश्किल है। यदि अतिप्रवाह की मेरी गणित समझ सही है तो हम अधिकतम मान के बाद अगले नंबर से शुरू करते हैं।
अपडेट करें
जलश टिप्पणी के अनुसार
7.0 एक डबल है, फ्लोट नहीं है, 7.0f की कोशिश करें, यह अभी भी आपको 0 देगा
उनकी टिप्पणी सही है। यदि हम फ्लोट का उपयोग करते हैं तो आपको रोजलिन और .NET कोर के लिए 0 मिलता है, लेकिन दूसरी ओर 7 में दोहरे परिणाम का उपयोग करते हुए।
मैंने कुछ अतिरिक्त परीक्षण किए और चीजें भी अजीब हो गईं, लेकिन अंत में सब कुछ समझ में आता है (कम से कम थोड़ा)।
मेरा मानना है कि .NET फ्रेमवर्क 4.7.2 कंपाइलर (2018 के मध्य में जारी किया गया) वास्तव में .NET कोर 3.1 और रोसलिन 3.4 कंपाइलर (2019 के अंत में जारी) की तुलना में अलग-अलग अनुकूलन का उपयोग करता है। ये विभिन्न अनुकूलन / संगणनाएँ विशुद्ध रूप से संकलन-समय पर ज्ञात निरंतर मूल्यों के लिए उपयोग की जाती हैं। यही कारण है कि unchecked
कीवर्ड का उपयोग करने की आवश्यकता थी क्योंकि संकलक को पहले से ही पता है कि अतिप्रवाह हो रहा है, लेकिन अंतिम आईएल को अनुकूलित करने के लिए अलग-अलग गणना का उपयोग किया गया था।
समान स्रोत कोड और IL_000a निर्देश को छोड़कर लगभग समान IL। एक कंपाइलर 7 और अन्य 0 की गणना करता है।
सोर्स कोड
using System;
public class Program
{
const float scale = 64 * 1024;
public static void Main()
{
Console.WriteLine(unchecked((uint)(ulong)(1.2 * scale * scale + 1.5 * scale)));
Console.WriteLine(unchecked((uint)(scale * scale + 7.0)));
}
}
.NET फ्रेमवर्क (x64) आईएल
.class private auto ansi '<Module>'
{
} // end of class <Module>
.class public auto ansi beforefieldinit Program
extends [mscorlib]System.Object
{
// Fields
.field private static literal float32 scale = float32(65536)
// Methods
.method public hidebysig static
void Main () cil managed
{
// Method begins at RVA 0x2050
// Code size 17 (0x11)
.maxstack 8
IL_0000: ldc.i4 859091763
IL_0005: call void [mscorlib]System.Console::WriteLine(uint32)
IL_000a: ldc.i4.7
IL_000b: call void [mscorlib]System.Console::WriteLine(uint32)
IL_0010: ret
} // end of method Program::Main
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x2062
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method Program::.ctor
} // end of class Program
रोजलिन कंपाइलर शाखा (सितंबर 2019) आईएल
.class private auto ansi '<Module>'
{
} // end of class <Module>
.class public auto ansi beforefieldinit Program
extends [System.Private.CoreLib]System.Object
{
// Fields
.field private static literal float32 scale = float32(65536)
// Methods
.method public hidebysig static
void Main () cil managed
{
// Method begins at RVA 0x2050
// Code size 17 (0x11)
.maxstack 8
IL_0000: ldc.i4 859091763
IL_0005: call void [System.Console]System.Console::WriteLine(uint32)
IL_000a: ldc.i4.0
IL_000b: call void [System.Console]System.Console::WriteLine(uint32)
IL_0010: ret
} // end of method Program::Main
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x2062
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [System.Private.CoreLib]System.Object::.ctor()
IL_0006: ret
} // end of method Program::.ctor
} // end of class Program
जब आप unchecked
नीचे की तरह गैर-स्थिर अभिव्यक्ति (डिफ़ॉल्ट रूप से ) जोड़ते हैं तो यह सही तरीके से जाना शुरू कर देता है ।
using System;
public class Program
{
static Random random = new Random();
public static void Main()
{
var scale = 64 * random.Next(1024, 1025);
uint f = (uint)(ulong)(scale * scale + 7f);
uint d = (uint)(ulong)(scale * scale + 7d);
uint i = (uint)(ulong)(scale * scale + 7);
Console.WriteLine((uint)(ulong)(1.2 * scale * scale + 1.5 * scale)); // 859091763
Console.WriteLine((uint)(ulong)(scale * scale + 7f)); // 7
Console.WriteLine(f); // 7
Console.WriteLine((uint)(ulong)(scale * scale + 7d)); // 7
Console.WriteLine(d); // 7
Console.WriteLine((uint)(ulong)(scale * scale + 7)); // 7
Console.WriteLine(i); // 7
}
}
जो दोनों कंपाइलरों द्वारा "बिल्कुल" समान आईएल उत्पन्न करता है।
.NET फ्रेमवर्क (x64) आईएल
.class private auto ansi '<Module>'
{
} // end of class <Module>
.class public auto ansi beforefieldinit Program
extends [mscorlib]System.Object
{
// Fields
.field private static class [mscorlib]System.Random random
// Methods
.method public hidebysig static
void Main () cil managed
{
// Method begins at RVA 0x2050
// Code size 164 (0xa4)
.maxstack 4
.locals init (
[0] int32,
[1] uint32,
[2] uint32
)
IL_0000: ldc.i4.s 64
IL_0002: ldsfld class [mscorlib]System.Random Program::random
IL_0007: ldc.i4 1024
IL_000c: ldc.i4 1025
IL_0011: callvirt instance int32 [mscorlib]System.Random::Next(int32, int32)
IL_0016: mul
IL_0017: stloc.0
IL_0018: ldloc.0
IL_0019: ldloc.0
IL_001a: mul
IL_001b: conv.r4
IL_001c: ldc.r4 7
IL_0021: add
IL_0022: conv.u8
IL_0023: conv.u4
IL_0024: ldloc.0
IL_0025: ldloc.0
IL_0026: mul
IL_0027: conv.r8
IL_0028: ldc.r8 7
IL_0031: add
IL_0032: conv.u8
IL_0033: conv.u4
IL_0034: stloc.1
IL_0035: ldloc.0
IL_0036: ldloc.0
IL_0037: mul
IL_0038: ldc.i4.7
IL_0039: add
IL_003a: conv.i8
IL_003b: conv.u4
IL_003c: stloc.2
IL_003d: ldc.r8 1.2
IL_0046: ldloc.0
IL_0047: conv.r8
IL_0048: mul
IL_0049: ldloc.0
IL_004a: conv.r8
IL_004b: mul
IL_004c: ldc.r8 1.5
IL_0055: ldloc.0
IL_0056: conv.r8
IL_0057: mul
IL_0058: add
IL_0059: conv.u8
IL_005a: conv.u4
IL_005b: call void [mscorlib]System.Console::WriteLine(uint32)
IL_0060: ldloc.0
IL_0061: ldloc.0
IL_0062: mul
IL_0063: conv.r4
IL_0064: ldc.r4 7
IL_0069: add
IL_006a: conv.u8
IL_006b: conv.u4
IL_006c: call void [mscorlib]System.Console::WriteLine(uint32)
IL_0071: call void [mscorlib]System.Console::WriteLine(uint32)
IL_0076: ldloc.0
IL_0077: ldloc.0
IL_0078: mul
IL_0079: conv.r8
IL_007a: ldc.r8 7
IL_0083: add
IL_0084: conv.u8
IL_0085: conv.u4
IL_0086: call void [mscorlib]System.Console::WriteLine(uint32)
IL_008b: ldloc.1
IL_008c: call void [mscorlib]System.Console::WriteLine(uint32)
IL_0091: ldloc.0
IL_0092: ldloc.0
IL_0093: mul
IL_0094: ldc.i4.7
IL_0095: add
IL_0096: conv.i8
IL_0097: conv.u4
IL_0098: call void [mscorlib]System.Console::WriteLine(uint32)
IL_009d: ldloc.2
IL_009e: call void [mscorlib]System.Console::WriteLine(uint32)
IL_00a3: ret
} // end of method Program::Main
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x2100
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method Program::.ctor
.method private hidebysig specialname rtspecialname static
void .cctor () cil managed
{
// Method begins at RVA 0x2108
// Code size 11 (0xb)
.maxstack 8
IL_0000: newobj instance void [mscorlib]System.Random::.ctor()
IL_0005: stsfld class [mscorlib]System.Random Program::random
IL_000a: ret
} // end of method Program::.cctor
} // end of class Program
रोजलिन कंपाइलर शाखा (सितंबर 2019) आईएल
.class private auto ansi '<Module>'
{
} // end of class <Module>
.class public auto ansi beforefieldinit Program
extends [System.Private.CoreLib]System.Object
{
// Fields
.field private static class [System.Private.CoreLib]System.Random random
// Methods
.method public hidebysig static
void Main () cil managed
{
// Method begins at RVA 0x2050
// Code size 164 (0xa4)
.maxstack 4
.locals init (
[0] int32,
[1] uint32,
[2] uint32
)
IL_0000: ldc.i4.s 64
IL_0002: ldsfld class [System.Private.CoreLib]System.Random Program::random
IL_0007: ldc.i4 1024
IL_000c: ldc.i4 1025
IL_0011: callvirt instance int32 [System.Private.CoreLib]System.Random::Next(int32, int32)
IL_0016: mul
IL_0017: stloc.0
IL_0018: ldloc.0
IL_0019: ldloc.0
IL_001a: mul
IL_001b: conv.r4
IL_001c: ldc.r4 7
IL_0021: add
IL_0022: conv.u8
IL_0023: conv.u4
IL_0024: ldloc.0
IL_0025: ldloc.0
IL_0026: mul
IL_0027: conv.r8
IL_0028: ldc.r8 7
IL_0031: add
IL_0032: conv.u8
IL_0033: conv.u4
IL_0034: stloc.1
IL_0035: ldloc.0
IL_0036: ldloc.0
IL_0037: mul
IL_0038: ldc.i4.7
IL_0039: add
IL_003a: conv.i8
IL_003b: conv.u4
IL_003c: stloc.2
IL_003d: ldc.r8 1.2
IL_0046: ldloc.0
IL_0047: conv.r8
IL_0048: mul
IL_0049: ldloc.0
IL_004a: conv.r8
IL_004b: mul
IL_004c: ldc.r8 1.5
IL_0055: ldloc.0
IL_0056: conv.r8
IL_0057: mul
IL_0058: add
IL_0059: conv.u8
IL_005a: conv.u4
IL_005b: call void [System.Console]System.Console::WriteLine(uint32)
IL_0060: ldloc.0
IL_0061: ldloc.0
IL_0062: mul
IL_0063: conv.r4
IL_0064: ldc.r4 7
IL_0069: add
IL_006a: conv.u8
IL_006b: conv.u4
IL_006c: call void [System.Console]System.Console::WriteLine(uint32)
IL_0071: call void [System.Console]System.Console::WriteLine(uint32)
IL_0076: ldloc.0
IL_0077: ldloc.0
IL_0078: mul
IL_0079: conv.r8
IL_007a: ldc.r8 7
IL_0083: add
IL_0084: conv.u8
IL_0085: conv.u4
IL_0086: call void [System.Console]System.Console::WriteLine(uint32)
IL_008b: ldloc.1
IL_008c: call void [System.Console]System.Console::WriteLine(uint32)
IL_0091: ldloc.0
IL_0092: ldloc.0
IL_0093: mul
IL_0094: ldc.i4.7
IL_0095: add
IL_0096: conv.i8
IL_0097: conv.u4
IL_0098: call void [System.Console]System.Console::WriteLine(uint32)
IL_009d: ldloc.2
IL_009e: call void [System.Console]System.Console::WriteLine(uint32)
IL_00a3: ret
} // end of method Program::Main
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x2100
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [System.Private.CoreLib]System.Object::.ctor()
IL_0006: ret
} // end of method Program::.ctor
.method private hidebysig specialname rtspecialname static
void .cctor () cil managed
{
// Method begins at RVA 0x2108
// Code size 11 (0xb)
.maxstack 8
IL_0000: newobj instance void [System.Private.CoreLib]System.Random::.ctor()
IL_0005: stsfld class [System.Private.CoreLib]System.Random Program::random
IL_000a: ret
} // end of method Program::.cctor
} // end of class Program
इसलिए, अंत में मेरा मानना है कि विभिन्न व्यवहार का कारण रूपरेखा और / या संकलक का एक अलग संस्करण है जो निरंतर अभिव्यक्तियों के लिए अलग-अलग अनुकूलन / संगणना का उपयोग कर रहे हैं, लेकिन अन्य मामलों में व्यवहार बहुत ही समान है।
ulong
बाद के मामले में कलाकारों को नजरअंदाज किया जा रहा है इसलिए यह रूपांतरणfloat
->int
रूपांतरण में हो रहा है ।