رفتن به محتوای اصلی
بازگشت به وبلاگ

داده و اتصال فنی

جمع float؛ چرا جابه‌جاییِ سه عدد نتیجه را عوض می‌کند؟

جمع float را در شش ترتیب با حلقه،sum وfsum بسنجید؛ oracleِکسر از ورودیِ واقعی ساخته می‌شود و بازیابیِ قصدِ دهدهی ادعا نمی‌شود.

جمعِ عددهایِ اعشاریِ ممیزشناور می‌تواند به ترتیبِ محاسبه و الگوریتمِ جمع وابسته باشد. برای دیدنِ علت، سه floatِ بزرگ، کوچک و منفی را با حلقهٔ ساده، sum وmath.fsum مقایسه می‌کنیم. مرجعِ دقیقِ این آزمایش کسرِ ساخته‌شده از همان floatهایِ موجود است؛ از این مرجع، رقمِ دهدهیِ اولیهٔ گم‌شده را حدس نمی‌زنیم.

یک واحد در کنارِ عددِ بسیار بزرگ

سه مقدارِ اصیل۱e16،۱٫۰ و−۱e16 را داریم. جمعِ ریاضیِ همین سه مقدار۱ است. در حلقه‌ای که total از۰٫۰ شروع و هر بار با += به‌روزرسانی می‌شود، افزودنِ ۱به۱e16 در این نمایش ممکن است آن واحد را حفظ نکند. کم‌کردنِ مقدارِ بزرگِ بعدی، اطلاعاتِ حذف‌شده را برنمی‌گرداند.

در اجرایِ واقعیِ Python۳٫۱۲٫۱۴، حلقهٔ ساده برای ترتیبِ[۱e16،۱،−۱e16] نتیجهٔ۰٫۰ می‌دهد. برایِ[۱e16،−۱e16،۱] نتیجه۱٫۰ است. این اختلاف را با تغییرِ داده، خطایِ schema یا تصمیمِ مدل توضیح نمی‌دهیم؛ همان سه float با ترتیبِ متفاوت جمع شده‌اند.

همهٔ شش ترتیب را بسنجیم

به یک چینشِ انتخابی اکتفا نکرده‌ایم. تمامِ شش جایگشتِ سه مقدار اجرا و خروجیِ هر سه روش ثبت می‌شود. حلقهٔ ساده در این مجموعه۰ یا۱ می‌دهد؛ sumِ همین runtime وmath.fsum برای هر شش،۱ می‌دهند. فایلِ JSON همهٔ سطرها را دارد و فقط نتیجهٔ مطلوب پنهانی انتخاب نشده است.

ترتیبِ نمونهحلقهٔ +=sum در اجرایِ ثبت‌شدهmath.fsum
[۱e16،۱،−۱e16]۰۱۱
[۱e16،−۱e16،۱]۱۱۱

نباید نتیجهٔ حلقه را بی‌بررسی به تابعِ sumِ هر نسخه نسبت بدهیم. مستندات Python تغییرِ الگوریتمِ جمعِ float را از۳٫۱۲ بیان می‌کند. اینجا مشاهدهٔ همان نسخه ثبت شده است؛ جدول به معنیِ آزمونِ همهٔ نسخه‌ها یا پلتفرم‌ها نیست.

مرجعِ دقیق، از کدام داده ساخته شد؟

برای هر ورودی Fraction.from_float می‌گیریم و کسرها را با محاسبهٔ دقیق جمع می‌کنیم. حاصلِ سه عددِ اصلی دقیقاً۱ است. این oracle از الگوریتمِ fsum استفاده نمی‌کند و به همین دلیل مقایسهٔ مستقلی برایِ این fixture می‌دهد. همهٔ ورودی‌ها متناهی و تعدادشان سه است؛ overflow،NaN یا جریانِ بسیار بزرگ بررسی نشده‌اند.

در آزمایشِ جدا، سه floatِ ۰٫۱ را به همین روشِ کسر تبدیل می‌کنیم. حاصلِ دقیقِ مقدارهایِ binaryِ ذخیره‌شده برابرِ ۱۰۸۰۸۶۳۹۱۰۵۶۸۹۱۹۱÷۳۶۰۲۸۷۹۷۰۱۸۹۶۳۹۶۸ است و با۳÷۱۰ِ دهدهی برابر نیست. دقیق‌جمع‌کردنِ ورودیِ موجود، معنایِ دهدهیِ قبل از تبدیل را خودکار بازسازی نمی‌کند.

fsum چه چیزی را بهتر نگه می‌دارد؟

math.fsum چند جمعِ میانی را نگه می‌دارد تا افتِ دقتِ جمع کاهش پیدا کند. مستندات برایِ دقت به فرض‌هایِ arithmetic و حالتِ rounding اشاره می‌کند و برای بعضی محیط‌ها محدودیتِ آخرین بیت دارد. این مثالِ موفق، اثباتِ پاسخِ کاملاً دقیق برایِ هر توالیِ دلخواه یا هر محیط نیست.

اگر نیاز، مقدارِ دهدهیِ صریح و قاعدهٔ گردکردن است، Decimal از رشته پرسشِ دیگری را پاسخ می‌دهد. اگر نیاز، حفظِ شناسهٔ بزرگ هنگامِ انتقال است، رفت‌وبرگشتِ عددِ بزرگ در JSON را ببینید. این سه مسئله را با توصیهٔ کلیِ «نوع را عوض کنید» یکی نکنیم.

در گزارشِ محاسبات چه چیزی بنویسیم؟

نوعِ ورودی، نسخهٔ runtime، ترتیبِ جمع، الگوریتم و معیارِ مقایسه را مشخص کنید. برایِ نمونهٔ کوچک، یک oracleِ مستقل از مقدارهایِ واقعاً‌ذخیره‌شده بسازید. در استانداردسازی داده، جمع بخشی از محاسبهٔ مرجع است؛ دقتِ جمع همچنان جای کنترلِ منشأِ داده و جلوگیری از نشت را نمی‌گیرد.

برای ادامه به مبانی هوش مصنوعی بروید. کدِ همراه فقط محاسبهٔ محدودِ حافظه‌ای با کتابخانهٔ استاندارد است؛ هیچ مدل، دادهٔ مشتری، قیمت یا عملیاتِ مالی اجرا نشده و هیچ افزایشِ دقتِ محصول اپرا از آن نتیجه نمی‌شود.

فایل تمرین و منبع

کد مستقلِ تمرینِ محدود · تمام خروجیِ واقعیِ همین تمرین؛ JSON

منابع در 2026-11-04 خوانده شدند؛ این تاریخ، تاریخ انتشار منبع نیست. مثال‌ها و فایل‌های این راهنما آموزشی و ساختهٔ تحریریه‌اند.

برای این نیاز، کدام خدمت مناسب‌تر است؟

تماس و منشی، چت سایت و تحلیل مکالمه سه مسیر متفاوت‌اند. ابتدا خدمت متناسب نیازتان را انتخاب کنید.

انتخاب میان سه خدمتراهنمای شروع با تیم اپرا

برآورد هزینه