تقريب Double في Swift: أفضل 5 ممارسات لعام 2025

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

لماذا تقريب Double في Swift مؤلم (وكيف تتعايش معه في 2025)



كل مطور iOS يواجه عاجلاً أم آجلاً موقفاً: يحتاج لعرض سعر منتج للمستخدم 99.99، بينما في الكود 99.99000000000001. مألوف؟ مرحباً بك في عالم تقريب Double في Swift — الموضوع الذي جمع آلاف المشاهدات على Stack Overflow ولا يزال يشغل الأذهان حتى في 2025.



المشكلة ليست في Swift — المشكلة في طبيعة الأعداد ذات الفاصلة العائمة (IEEE 754). لا يمكن لـ Double تمثيل 0.1 بدقة، تماماً مثل 1/3 في النظام العشري. لكن بالنسبة للمستخدم، هذا ليس عذراً. إنه يحتاج أرقاماً جميلة على الشاشة.



في هذه المقالة سأعرض 5 طرق مجربة لتقريب Double في Swift، وسأشرح إيجابياتها وسلبياتها، وسأقدم خوارزمية واضحة للاختيار حسب مهمتك. هيا بنا!



الطريقة 1: Foundation — round() + pow(10, n) — الكلاسيكية



الطريقة الأكثر وضوحاً التي تتبادر إلى الذهن: ضرب الرقم في 10^n، تقريبه، ثم قسمته مرة أخرى.



import Foundation

func roundDouble(_ value: Double, toPlaces places: Int) -> Double { let divisor = pow(10.0, Double(places)) return round(value * divisor) / divisor}

let price = 99.995print(roundDouble(price, toPlaces: 2)) // 100.0 (تقريب مصرفي)


الإيجابيات:

  • البساطة وسهولة القراءة
  • يعمل "مباشرة" — لا حاجة لاستيرادات إضافية


السلبيات:

  • أخطاء الدقة — بسبب Double قد تحصل على 99.99000000000001 بدلاً من 99.99
  • مشكلة التقريب المصرفي — round() تستخدم round half up، وهذا لا يناسب دائماً الأمور المالية
  • pow(10, n) — عمليات حسابية زائدة


هذه الطريقة مناسبة للتقريب التقريبي في واجهة المستخدم، لكنها ليست للحسابات المالية.



الطريقة 2: String(format:) — التقريب عبر النص (الأسرع لواجهة المستخدم)



إذا كان هدفك النهائي هو عرض الرقم على الشاشة، فلماذا تتعامل مع Double أصلاً؟ حوله إلى نص فوراً.



let value = 123.456789let roundedString = String(format: "%.2f", value)print(roundedString) // "123.46"

// العودة إلى Double (إذا لزم الأمر)let roundedDouble = Double(roundedString) ?? 0.0


الإيجابيات:

  • سرعة فائقة — لا عمليات رياضية زائدة
  • عدد مضمون وصحيح من المنازل في المخرجات
  • دعم التوطين (فاصل عشري)


السلبيات:

  • النتيجة نصية، وللحسابات اللاحقة تحتاج للتحويل مرة أخرى (فقدان دقة)
  • غير مناسبة للتقريب المصرفي (round half up افتراضياً)


مثالية لعرض الأسعار، النسب المئوية، التقييمات — في كل مكان حيث الدقة ±0.01 غير حرجة.



الطريقة 3: NSDecimalNumber — ملك الدقة المالية



عندما تكون الأموال على المحك، Double هو الشر. استخدم NSDecimalNumber — فهو يخزن الأرقام بصيغة عشرية دون أخطاء تقريب.



import Foundation

func roundDecimal(_ value: Double, toPlaces places: Int, roundingMode: NSDecimalNumber.RoundingMode = .plain) -> Double { let decimal = NSDecimalNumber(value: value) let handler = NSDecimalNumberHandler( roundingMode: roundingMode, scale: Int16(places), raiseOnExactness: false, raiseOnOverflow: false, raiseOnUnderflow: false, raiseOnDivideByZero: false ) return decimal.rounding(accordingToBehavior: handler).doubleValue}

let amount = 99.995print(roundDecimal(amount, toPlaces: 2, roundingMode: .bankers)) // 99.99 (تقريب مصرفي!)


الإيجابيات:

  • تحكم كامل في التقريب — .plain, .down, .up, .b

المدونات

توصيات الكتب