وصف المشكلة
عند استخدام Java لحساب أرقام النقاط العائمة في المشروع ، وجد أنه بالنسبة لحسابات مثل 4.015*100 ، لم تكن النتيجة هي 401.5 المتوقعة ، ولكن 401.4999999999999999999999999999994. مثل هذا العدد الطويل من الأرقام غير ودية للعرض.
سبب المشكلة: تمثيل رقم النقطة العائمة
بعد استشارة المعلومات ذات الصلة ، وجدت أن السبب هو أنه لا يمكن التعبير عن أرقام النقاط العائمة في الكمبيوتر بدقة. على سبيل المثال ، بالنسبة لنوع مزدوج 38414.4 ، يقوم الكمبيوتر بتخزينه على هذا النحو:
تحويل إلى ثنائي: 100101100001110.01100110011001100110011001100110011001100
تحول إلى موضوع
تعلم طريقة العد: 1.001011000011100110011001100110011001100110011001100110011001100 × 2^15
تنسيق الترميز المزدوج كما يلي:
Double Sign Sign Bit 1 Code Stage Code 11 Mantissa 52 Sigits
البت الرمز: الرقم الإيجابي هو 0
رمز الطلب: 15 هو رقم إيجابي ، وبالتالي فإن أعلى عدد هو 1 ، وأدنى بت هو ناقص 1 ، وهو 10000001110
Mantissue: قم بإزالة الافتراضي 1 من أعلى بت ، وهو 0010110000111001100110011001100110011001100110011001100
مجتمعة ، الترميز النهائي هو: 0 1000001110 00101100001110011001100110011001100110011001100110011001100
من هنا ، يمكننا أن نرى أن السبب الرئيسي هو أن الترميز الثنائي يجعل الجزء الكسري مستحيل التعبير تمامًا تمامًا ، مثل 0.4 = 0.25 + 0.125 + ... ، والذي لا يمكن أن يكون سوى قرب بلا حدود. لذلك ، ستحدث أخطاء الدقة عند حساب أرقام النقاط العائمة.
الحل: دقة عالية
يمكن أن تدعم BigDecimal في Java عمليات أرقام النقطة العائمة بدقة تعسفية. في كتاب "Java الفعال" ، يوصى باستخدام التعويم والمضاعفة للحسابات العلمية أو الحسابات الهندسية ، في حين يتم استخدام java.math.bigdecimal في الحسابات التجارية.
هناك العديد من أساليب البناء لـ BigDecimal ، مثل BigDecimal (double) و BigDecimal (سلسلة). تجدر الإشارة إلى أن معلمات البناء هي نوع السلسلة للتأكد من عدم فقد الدقة ، لأن النوع المزدوج نفسه دقيق تمامًا. لذلك ، يجب كتابتها على النحو التالي: BigDecimal ("0.02").
يمكن العثور على العمليات الأساسية من النوع المزدوج في BigDecimal. بالإضافة إلى ذلك ، يمكن أيضًا استخدام BigDecimal لتنسيق الإخراج باستخدام NumberFormat.
ستقوم BigDecimal بإنشاء كائنات كبيرة جديدة عند القيام بعمليات ، لذلك ستجلب المزيد من الأداء مقارنة بالمضاعفة.
دراسة أولية حول التنفيذ عالي الدقة
فكيف يكون BigDecimal قادرًا على تمثيل الدقة التعسفية؟ هنا فقط تحليل أولي.
أولاً ، دعونا نلقي نظرة على تنفيذ BigInteger. نوع int العادي هو 32 بت ، لذلك هناك قيود النطاق. لدى BigInteger متغير الأعضاء int [] MAG ، بحيث يجعل صفيف int الأطول من الممكن تمثيل الأعداد الصحيحة من أي حجم.
دعونا نلقي نظرة على تنفيذ BigDecimal. تشير مقدمةها الرسمية إلى أنه يمكن تمثيل أي bigdecimal على أنه غير محدد × 10^. UncaledValue هو عدد صحيح من أي حجم ، يتوافق مع متغير الأعضاء Biginteger Intval في الكود المصدر ؛ المقياس هو الترتيب ، المقابل لمقياس المتغير المتغير في رمز المصدر. بهذه الطريقة ، يتم تنفيذ BigDecimal على أساس BigInteger.
ما سبق هو الحل لمشكلة دقة النقطة العائمة في جافا التي قدمها لك المحرر. آمل أن يكون ذلك مفيدًا لك. إذا كان لديك أي أسئلة ، يرجى ترك رسالة لي.