معرفی انواع اعشاری ممیز شناور استاندارد IEEE 754 در داتنت ۱۱
نویسنده: وحید نصیری
تاریخ: ۱۴۰۵/۰۵/۲۸ ۰۸:۴۰
آدرس: www.dntips.ir
چکیده: محاسبات ممیز شناور همواره یکی از چالشهای بنیادین در مهندسی نرمافزار، سیستمهای مالی و محاسبات علمی بودهاند. تا پیش از این، توسعهدهندگان اکوسیستم داتنت برای محاسبات دقیق بر پایهٔ مبنای ۱۰، منحصراً به نوع دادهٔSystem.Decimalمتکی بودند. با وجود دقت مناسب، این نوع داده با استاندارد بینالمللی IEEE 754-2019 سازگار نبود و از مقادیر ویژه (نظیر بینهایت یاNaN) و محاسبات عام (Generic Math) به شکل شناور پشتیبانی کاملی به عمل نمیآورد. فضای نامSystem.Numericsسه نوع دادهٔ اعشاری جدید با نامهایDecimal32،Decimal64وDecimal128معرفی کرده است که پیادهسازی رسمی فرمتهای استاندارد اعشاری ممیز شناور IEEE 754 هستند. این مقاله به بررسی ویژگیها، معماری کدگذاری Binary Integer Decimal (BID)، رابطهای Generic Math و مقایسهٔ کاربردی این ساختارها با انواع دادهٔ سنتی میپردازد.
float (Single) و double (Double) که بر مبنای پایهٔ ۲ کار میکنند. این انواع به دلیل ناتوانی در نمایش دقیق کسرهای مبنای ۱۰ (مانند 0.1 یا 0.01)، در محاسبات حساس مالی یا مقادیری که نیازمند دقت کسری دقیق هستند، منجر به خطاهای گردکردن (Rounding Artifacts) میشوند.System.Decimal با اندازهٔ ۱۲۸ بیت و دقت ۲۸ الی ۲۹ رقم اعشار، سالها راهکار استاندارد داتنت برای سامانههای مالی بوده است.System.Decimal دارای محدودیتهای ساختاری مشخصی است:NaN یا Not-a-Number) پشتیبانی نمیکند.System.Numerics ارائه شدهاند:| نام نوع داده (Type) | اندازه در حافظه (Size) | دقت اعشاری (Decimal Precision) | محدوده توان اعشاری (Exponent Range) | سناریوی کاربرد اصلی |
Decimal32 | ۳۲ بیت (۴ بایت) | ۷ رقم بامعنی | کسرها و دامنههای فشرده | سیستمهای نهفته، مدلهای وزندهی سبک، ذخیرهسازی ابری حجیم |
Decimal64 | ۶۴ بیت (۸ بایت) | ۱۶ رقم بامعنی | گسترهٔ استاندارد مالی | جایگزین سبک و استاندارد برای اکثر محاسبات تجاری و ارزی |
Decimal128 | ۱۲۸ بیت (۱۶ بایت) | ۳۴ رقم بامعنی | بسیار وسیع | محاسبات علمی بسیار دقیق، ابزارهای مالی مشتقه و استاندارد IEEE |
PositiveInfinity، NegativeInfinity و انواع NaN (Quiet و Signaling).IDecimalFloatingPointIeee754 را پیادهسازی میکنند که خود مشتقشده از IFloatingPointIeee754 و IFloatingPoint است. به کمک این قابلیت، میتوان توابع محاسباتی جنریک نوشت که بدون وابستگی به یک نوع دادهٔ خاص، هم با float/double و هم با انواع جدید Decimal32/Decimal64/Decimal128 کار کنند.using System;
using System.Numerics;
public class FinancialEngine
{
// متد جنریک برای گردکردن با الگوریتم بانکی (MidpointRounding.ToEven)
public static T RoundToCents<T>(T value) where T : IFloatingPoint<T>
{
return T.Round(value, digits: 2, MidpointRounding.ToEven);
}
public static void Execute()
{
// استفاده از Decimal64 برای کاهش مصرف حافظه نسبت به Decimal سنتی
Decimal64 price = Decimal64.Parse("19.95");
Decimal64 taxRate = Decimal64.Parse("0.0875");
Decimal64 subtotal = price * (Decimal64.One + taxRate);
Decimal64 finalTotal = RoundToCents(subtotal);
Console.WriteLine($"Price: {price}");
Console.WriteLine($"Total with Tax: {finalTotal}"); // خروجی: 21.70
}
}FMA)، انواع جدید توابع ریاضیاتی مانند ریشهگیری (Sqrt)، لگاریتم (Log) و مثلثات را با حفظ قوانین توان استاندارد ارائه میدهند.نکته فنی: توابع ریاضی پایه کاملاً Bit-Exact هستند. پیادهسازی توابع متعالی (Transcendental) در نسخههای آغازین، تقریبهای بسیار دقیق استاندارد را ارائه میدهند و مایکروسافت برنامهریزی کرده است تا در نسخههای آتی دقت بیتی کامل آنها را نیز نهایی کند.
using System;
using System.Numerics;
public class AdvancedMathDemo
{
public static void Run()
{
// بررسی لگاریتم طبیعی عدد نپر
Decimal128 naturalLog = Decimal128.Log(Decimal128.E);
Console.WriteLine($"ln(e) ≈ {naturalLog}"); // حدود 1
// محاسبه جذر ۲ با دقت ۳۴ رقم اعشار
Decimal128 two = Decimal128.Parse("2");
Decimal128 sqrtTwo = Decimal128.Sqrt(two);
Console.WriteLine($"Sqrt(2) [34 digits]: {sqrtTwo}");
// خروجی: 1.414213562373095048801688724209698
// بررسی مدیریت سرریز و مقادیر ویژه IEEE
Decimal64 overflowValue = Decimal64.MaxValue * Decimal64.Parse("2");
Console.WriteLine($"Overflow is handled gracefully: {overflowValue}"); // خروجی: Infinity
}
}System.Decimalبا انواع استانداردDecimalN| ویژگی | System.Decimal (سنتی) | Decimal32 / 64 / 128 (استاندارد IEEE) |
| استاندارد | فرمت انحصاری داتنت | استاندارد بینالمللی IEEE 754-2019 |
| گزینههای اندازه | فقط ۱۲۸ بیت | انعطافپذیر (۳۲، ۶۴ و ۱۲۸ بیت) |
| رفتار در سرریز (Overflow) | پرتاب استثنای OverflowException | تولید مقدار بینهایت (مشابه استانداردهای ممیز شناور) |
| پشتیبانی از NaN | خیر | بله (NaN ، Signaling NaN) |
| کدگذاری داخلی | فرمت داتنت (Scale + Mantissa) | فرمت بهینه BID (سازگار با سختافزار) |
| تعاملپذیری (Interoperability) | نیازمند نگاشت سفارشی به ساختارهای C++/C | تبادل مستقیم بیتی با پایگاههای داده و کتابخانههای بومی (C/C++, Python) |
Decimal32، Decimal64 و Decimal128 گامی بلند در جهت بلوغ محاسبات عددی در اکوسیستم داتنت به شمار میرود. این انواع، فاصلهٔ میان دقت مبنای ۱۰ و سازگاری با استانداردهای بینالمللی ممیز شناور IEEE را به زیبایی پر میکنند.Decimal64 به جای Decimal، مصرف حافظه در مدلهای داده را به نصف کاهش دهند.