تفاوتهای تابع INT و CONVERT در DAX
نوشتن تبدیل نوع داده بهصورت صریح (Explicit Type Conversion) در DAX کار رایجی نیست، زیرا در اغلب موارد، تبدیلهای ضمنی (Implicit Conversions) که میان انواع مختلف داده در عبارات ریاضی انجام میشوند، همان نتایج مورد انتظار شما را فراهم میکنند.
با این حال، گاهی نیاز داریم نوع داده را بهصورت اجباری تغییر دهیم. این کار میتواند دلایل مختلفی داشته باشد، از جمله:
گرد کردن یک عدد (Round a Number)
یا اطمینان از اینکه یک محاسبه همیشه به یک روش خاص تقریب زده میشود (Ensure Consistent Approximation).
بهطور خاص، تبدیل یک مقدار به عدد صحیح (Integer) را میتوان از طریق چند روش مختلف انجام داد — روشهایی که در برخی شرایط مرزی (Borderline Cases) ممکن است نتایج متفاوتی تولید کنند.
در این مقاله، تفاوت بین دو روش اصلی تبدیل عدد به عدد صحیح را بررسی میکنیم: توابع INT و CONVERT.
تابع INT از همان نسخههای اولیه DAX وجود داشته است، در حالی که تابع CONVERT نسبتاً جدیدتر بوده و از سال ۲۰۱۹ معرفی شده است.
برای مثال، کد زیر عدد 32.34 را به عدد صحیح 32 تبدیل میکند:
INT ( 32.34 )
CONVERT ( 32.34, INTEGER )
تفاوت عملکرد و معناشناسی بین INT و CONVERT
ممکن است بخواهید بدانید کدامیک از این دو تابع از نظر کارایی (Performance) بهتر است.
در واقع، تفاوت محسوسی بین آنها وجود ندارد؛ هرچند تابع CONVERT اندکی سریعتر عمل میکند، اما این برتری بسیار جزئی بوده و در بیشتر سناریوها غیرقابلتوجه است.
تفاوت اصلی میان این دو تابع در سطح معناشناسی (Semantic Level) نهفته است:
تابع
CONVERTهمیشه مقدار را دقیقاً به نوع دادهای که مشخص کردهاید برمیگرداند (در این مثال،Integer).در مقابل، تابع
INTهمیشه مقدار صحیح برمیگرداند، اما نوع داده خروجی آن بسته به نوع آرگومان ممکن است متفاوت باشد — یعنی خروجی میتواند از نوعIntegerیاCurrencyباشد.
اگر آرگومان ورودی از نوع Floating Point باشد — که در Power BI به آن Decimal و در سینتکس DAX به آن DOUBLE گفته میشود — آنگاه خروجی تابع INT از نوع Integer خواهد بود.
اما اگر آرگومان از نوع Currency باشد — که در Power BI معادل Fixed Decimal Number است — نتیجه همچنان از نوع Currency برگردانده میشود، فقط عدد تا نزدیکترین مقدار صحیح گرد میشود.
مثال کاربردی: تفاوت در نتایج محاسبه
شاید بپرسید در چه مواقعی این تفاوت واقعاً اهمیت پیدا میکند؟
برای مشاهدهی اثر آن، به مثال زیر دقت کنید:
در این مثال، یک Query دو ستون جدید ایجاد میکند که هر دو حاصل ضرب مقدار Quantity در Amount هستند.
این دو ستون بهترتیب با نامهای Test CONVERT و Test INT شناخته میشوند.
برای محاسبهی این مقادیر، مقدار Amount ابتدا با استفاده از یکی از دو تابع CONVERT یا INT به عدد صحیح گرد شده است.
نتیجه این دو محاسبه را در جدول زیر میبینید؛ تفاوت خروجیها در ردیف C مشخص است:
DEFINE
TABLE Test =
DATATABLE (
"ID", STRING,
"Quantity", INTEGER,
"Amount", CURRENCY,
{
{ "A", 100000, 5000000000.33 },
{ "B", 150000, 5000000000.33 },
{ "C", 200000, 5000000000.33 }
}
)
EVALUATE
ADDCOLUMNS (
Test,
"Test CONVERT", Test[Quantity] * CONVERT ( Test[Amount], INTEGER ),
"Test INT", Test[Quantity] * INT ( Test[Amount] )
)
چرا این اتفاق میافتد؟
دلیل این تفاوت به نوع دادهی ستون Amount برمیگردد.
در این مثال، نوع دادهی Amount برابر با CURRENCY است (که در Power BI معادل نوع دادهی Fixed Decimal Number محسوب میشود).
زمانی که از تابع INT استفاده میکنیم، نوع دادهی آن تغییر نمیکند و خروجی همچنان از نوع Currency باقی میماند.
در مقابل، تابع CONVERT خروجی را بهصورت صریح به نوع Integer برمیگرداند.
در ردیف C، مقدار مورد انتظار عددی بزرگ است:
1,000,000,000,000,000 یا بهصورت نمایی 1E15.
این عدد بزرگ هنوز در محدودهی مجاز نوع Integer قرار دارد، چون حداکثر مقدار قابلنمایش برای Integer برابر است با:
9,223,372,036,854,775,807 یا 9.22E18.
اما حداکثر مقدار مجاز برای نوع Currency فقط 922,337,203,685,477 یا 9.22E14 است — یعنی کوچکتر از مقدار مورد انتظار برای ردیف C.
بنابراین نتیجهی ضرب در این حالت از محدودهی قابلنمایش نوع Currency فراتر میرود.
تفاوت در نوع داده ضرب (Multiplication)
ممکن است بپرسید:
وقتی تبدیل نوع برای مقدار Amount انجام شده و آن مقدار بهتنهایی در محدوده مجاز قرار دارد، چرا نتیجهی نهایی اشتباه میشود؟
پاسخ در نوع دادهی حاصل از عمل ضرب نهفته است:
وقتی دو مقدار از نوع Integer در هم ضرب میشوند (مثل ستون Test CONVERT)، نتیجه نیز از نوع Integer خواهد بود.
اما اگر یکی از مقادیر از نوع Currency و دیگری از نوع Integer باشد (مثل ستون Test INT)، نتیجهی نهایی از نوع Currency تولید میشود.
در این حالت، چون حاصلضرب از حداکثر مقدار مجاز نوع Currency فراتر میرود، نتیجهای غیرمنتظره یا اصطلاحاً “عجیب” ظاهر میشود.
خطای Overflow در DAX و رفتار Currency
وقتی از تابع INT استفاده میکنیم و پارامتری از نوع Currency به آن میدهیم، خروجی همچنان از نوع Currency باقی میماند.
در نتیجه، عمل ضرب بعدی بین یک مقدار Integer و یک مقدار Currency انجام میشود و خروجی نیز از نوع Currency خواهد بود.
اگر حاصل این ضرب از محدودهی قابلنمایش نوع Currency تجاوز کند، مقدار نهایی بهدرستی نمایش داده نمیشود.
چون نوع دادهی Currency در DAX بهصورت داخلی (Internally) با استفاده از ساختار Integer ذخیره میشود، در صورت وقوع Overflow (یعنی زمانی که عدد از ظرفیت نوع داده عبور کند)، فقط بخش کمارزشتر عدد (Least Significant Digits) ذخیره میشود و نتیجه معمولاً عددی منفی و غیرواقعی است.
این همان اتفاقی است که در ردیف C رخ داده است — خروجی منفی و ظاهراً تصادفی، در واقع ناشی از Overflow عددی است.
اهمیت انتخاب نوع داده مناسب در مدل DAX
در این مثال ساده، خطا بهوضوح دیده میشود و بهراحتی قابل توضیح است.
اما در مدلهای پیچیدهتر، بروز چنین خطاهایی میتواند باعث نتایج غیرمنتظره و محاسبات ظاهراً تصادفی شود که ردیابی و رفع آنها دشوار است.
در نهایت، هنگام کار با اعداد بزرگ — حتی اگر این اعداد در مراحل میانی محاسبه (Intermediate Steps) باشند — باید دقت کنید که نوع دادهی انتخابی و تبدیلهای ضمنی یا صریح (Implicit / Explicit Conversions) میتوانند تأثیر قابلتوجهی بر نتیجه نهایی داشته باشند.
دیدگاهتان را بنویسید