چرا در محاسبات مالی و فینتک هرگز نباید از Floating Point استفاده کرد؟
بررسی خطاهای پنهان استاندارد IEEE 754 در محاسبات اعشاری نرمافزارهای حسابداری و راهکارهای پیادهسازی موتور مالی با دقت دلخواه (Arbitrary Precision).
در سیستمهای مالی، حسابداری دوبل و درگاههای پرداخت، استفاده از انواع ممیز شناور (Float یا Double) میتواند منجر به خطاهای پنهان اعشاری شود. در این مقاله به بررسی علت این رخداد و راهکارهای تضمین تراز صفر مطلق میپردازیم.
چالش بازنمایی باینری در اعداد اعشاری
پردازندهها اعداد اعشاری را بر اساس استاندارد IEEE 754 به صورت باینری ذخیره میکنند. برخی اعداد دهدهی ساده مانند ۰.۱ بازنمایی متناهی در مبنای دو ندارند، بنابراین در محاسبات مقادیر بسیار کوچکی اختلاف به وجود میآید که در حجم بالای تراکنشها تراز مالی را مخدوش میکند.
// مثال خطای محاسباتی ممیز شناور:
const result = 0.1 + 0.2; // خروجی: 0.30000000000000004
// راهکار استاندارد با کتابخانههای دقت اعشار دلخواه:
import Decimal from 'decimal.js';
const safeResult = new Decimal('0.1').plus('0.2'); // خروجی دقیق: 0.3نکات کلیدی
- ذخیره مبالغ پولی در دیتابیس با نوع دادهای NUMERIC یا DECIMAL به جای FLOAT.
- تبادل مقادیر مالی در APIها در قالب رشته (String) برای جلوگیری از گرد شدن در کلاینت.
- انجام تمام محاسبات سود، زیان و مالیات با کتابخانههای Decimal.
اعتبارسنجی توازن اسناد مالی دوطرفه (Double-Entry)
در یک سیستم حسابداری استاندارد، مجموع ستون بدهکار (Debit) باید دقیقاً با ستون بستانکار (Credit) برابر باشد. پیش از ذخیره سند در دیتابیس، موتور ثبت سند باید توازن مطلق را تایید کند.
function isBalanced(entries: { debit: string; credit: string }[]): boolean {
let diff = new Decimal('0');
for (const entry of entries) {
diff = diff.plus(new Decimal(entry.debit)).minus(new Decimal(entry.credit));
}
return diff.isZero(); // تراز باید دقیقاً صفر باشد
}جمعبندی
در توسعه سامانههای مالی، دقت ریاضیاتی اولویت اول است. با کنار گذاشتن Float و استفاده از رویکرد رشتهای/Decimal، از مغایرتهای مالی جلوگیری میشود.