সবার আগে আপনি যাচাই না করা প্রসঙ্গটি ব্যবহার করছেন যা সংকলকটির জন্য একটি নির্দেশ যা আপনি নিশ্চিত, বিকাশকারী হিসাবে, ফলাফলটি উপচে পড়বে না এবং আপনি কোনও সংকলনের ত্রুটি দেখতে চান না। আপনার দৃশ্যে আপনি প্রকৃতপক্ষে প্রবহমান প্রকারে এবং তিনটি বিভিন্ন সংকলক জুড়ে ধারাবাহিক আচরণের প্রত্যাশা করছেন যা তাদের মধ্যে সম্ভবত রোজলিন এবং নেট নেটওয়ার্কের তুলনায় ইতিহাসের তুলনায় সামঞ্জস্যপূর্ণ যেটি নতুন।
দ্বিতীয় বিষয় আপনি অন্তর্নিহিত এবং স্পষ্ট রূপান্তর মিশ্রিত করা হয়। আমি রোজলিন সংকলক সম্পর্কে নিশ্চিত নই, তবে অবশ্যই। নেট ফ্রেমওয়ার্ক এবং। নেট কোর সংকলকগুলি এই ক্রিয়াকলাপগুলির জন্য বিভিন্ন অপ্টিমাইজেশন ব্যবহার করতে পারে।
এখানে সমস্যাটি হ'ল আপনার কোডের প্রথম লাইনটি কেবল ভাসমান পয়েন্টের মান / প্রকারগুলি ব্যবহার করে তবে দ্বিতীয় লাইনটি ভাসমান পয়েন্টের মান / প্রকার এবং অবিচ্ছেদ্য মান / প্রকারের সংমিশ্রণ।
আপনি সরাসরি ইন্টিজার ফ্লোটিং পয়েন্ট টাইপ করুন (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 জবাব দিয়েছি তার বিপরীতে বলব এবং এটি হ'ল বাগ (যদি এটি সত্যই কোনও বাগ হয়) রোজলিন এবং। নেট কোর সংকলকগুলিতে সম্ভবত "।
এটি বিশ্বাস করার আরেকটি কারণ হ'ল প্রথম চেক না করা গণনার ফলাফল সকলের জন্য একই এবং এটি এমন মান যে UInt32
টাইপের সর্বাধিক মানকে উপচে ফেলে ।
Console.WriteLine(unchecked((uint)(ulong)(1.2 * scale * scale + 1.5 * scale) - UInt32.MaxValue - 1)); // 859091763
আমরা শূন্য থেকে শুরু করার সাথে মাইনাস এক রয়েছে যা মানটি যা নিজেকে বিয়োগ করা শক্ত। ওভারফ্লো সম্পর্কে আমার গণিতের বোধগম্যতা যদি সঠিক হয় তবে আমরা সর্বাধিক মানের পরে পরবর্তী সংখ্যা থেকে শুরু করি।
হালনাগাদ
জলশ মন্তব্য অনুসারে
7.0 হ'ল একটি ডাবল, ভাসা নয়, চেষ্টা করুন 7.0f, এটি আপনাকে এখনও 0 দিবে
তাঁর মন্তব্যটি সঠিক। যদি আমরা ফ্লোট ব্যবহার করি তবে আপনি এখনও রোজলিন এবং। নেট কোরের জন্য 0 পান তবে অন্যদিকে 7-এ ডাবল ফলাফল ব্যবহার করে।
আমি কিছু অতিরিক্ত পরীক্ষা করেছি এবং জিনিসগুলি আরও অস্থির হয়ে উঠেছে, তবে শেষ পর্যন্ত সবকিছু বোধগম্য হয় (অন্তত কিছুটা)।
আমি যা অনুমান করি তা হ'ল নেট ফ্রেমওয়ার্ক 4.7.2 সংকলক (2018 সালের মাঝামাঝি সময়ে প্রকাশিত) .NET কোর 3.1 এবং রোজলিন 3.4 সংকলক (2019 এর শেষে প্রকাশিত) এর চেয়ে সত্যই বিভিন্ন অপ্টিমাইজেশন ব্যবহার করে। এই বিভিন্ন অপ্টিমাইজেশন / গণনা সংকলন সময়ে পরিচিত ধ্রুবক মান জন্য বিশুদ্ধভাবে ব্যবহৃত হয়। সে কারণেই unchecked
কীওয়ার্ডটি ব্যবহার করার প্রয়োজন ছিল কারণ সংকলক ইতিমধ্যে জানে যে ওভারফ্লো ঘটছে, তবে চূড়ান্ত আইএলকে অনুকূলকরণের জন্য আলাদা আলাদা গণনা ব্যবহৃত হয়েছিল।
IL_000a নির্দেশনা বাদে একই উত্স কোড এবং প্রায় একই আইএল। একটি সংকলক 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
রূপান্তরকরণে ঘটে ।