1. مقدمة
لاستعارة الكلمات من كتاب "Java الفعلي" ، فإن أهداف التصميم الرئيسية للأنواع العائمة والأنواع المزدوجة مخصصة للحوسبة العلمية والحوسبة الهندسية. إنهم يقومون بعمليات نقاط عائمة ثنائية ، والتي تم تصميمها بعناية لتوفير تقريب سريع أكثر دقة على النطاق العددي للمنطقة العريضة. ومع ذلك ، فإنها لا توفر نتائج دقيقة تمامًا ولا ينبغي استخدامها في المواقف التي تكون فيها النتائج الدقيقة مطلوبة. ومع ذلك ، غالبًا ما تتطلب الحسابات التجارية نتائج دقيقة ، ويأتي BigDecimal في متناول اليد في هذا الوقت.
2. مقدمة إلى BigDecimal
يتكون BigDecimal من قيمة غير صحيحة من أي دقة ومقياس عدد صحيح 32 بت. إذا كان صفرًا أو إيجابيًا ، فإن المقياس هو عدد الأرقام بعد النقطة العشرية. إذا كان الرقم السالب ، اضرب القيمة غير المقيدة للرقم بموجب طاقة مقياس سلبية قدرها 10. وبالتالي ، فإن القيمة التي يمثلها BigDecimal هي (UncaledValue × 10-scale).
3. رمز الاختبار
3.1 مُنشئ (أنواع معلمات الاختبار الرئيسية هما مُنشئان شائعان مع مزدوج وسلسلة)
نسخة الكود كما يلي: BigDecimal adouble = new BigDecimal (1.22) ؛
System.out.println ("بناء بقيمة مزدوجة:" + adouble) ؛
BigDecimal astring = new BigDecimal ("1.22") ؛
system.out.println ("بناء مع قيمة السلسلة:" + astring) ؛
ما رأيك في الإخراج سيكون؟ إذا كنت لا تعتقد أن أول واحد سوف يخرج 1.22 ، فهناك تهنئة الإجابة بشكل صحيح ، فإن نتيجة الإخراج هي كما يلي:
انسخ الرمز على النحو التالي: بناء مع القيمة المزدوجة: 1.2199999999999999999999733546474089962430298328399658203125
بناء بقيمة السلسلة: 1.22
وصف JDK:
1. نتائج طريقة البناء مع نوع المعلمة Double لا يمكن التنبؤ بها. قد يظن بعض الناس أن BigDecimal التي تم إنشاؤها عن طريق كتابة NewbigDecimal (0.1) في Java تساوي تمامًا 0.1 (قيمة غير تقليدية 1 ، والتي يكون مقياسها 1) ، ولكنها تساوي في الواقع 0.1000000000000000000000000055511512312570211815834041515625. وذلك لأنه لا يمكن التعبير عن 0.1 بدقة كضاعفة (أو لهذه الحالة لا يمكن التعبير عنها كأي عشري ثنائي الطول محدود). وبهذه الطريقة ، لن تكون القيمة التي تم تمريرها في طريقة البناء مساوية تمامًا لـ 0.1 (على الرغم من أنها تساوي هذه القيمة).
2. من ناحية أخرى ، يمكن التنبؤ تمامًا بأسلوب بناء السلسلة تمامًا: الكتابة إلى Newbigdecimal ("0.1") ستنشئ BigDecimal ، وهو ما يساوي تمامًا 0.1 المتوقع. لذلك ، بالمقارنة ، يوصى بشكل عام باستخدام مُنشئ السلسلة أولاً.
3. عندما يجب استخدام المزدوج كمصدر لـ BigDecimal ، يرجى ملاحظة أن هذا المُنشئ يوفر تحويلًا دقيقًا ؛ لا يوفر نفس النتيجة مثل العمليات التالية: استخدم أولاً طريقة Double.ToString (مزدوجة) ، ثم استخدم مُنشئ BigDecimal (سلسلة) لتحويل المزدوج إلى سلسلة. للحصول على النتيجة ، استخدم طريقة ثابتة (مزدوجة).
3.2 عملية إضافة
نسخة الكود كما يلي: BigDecimal A = New BigDecimal ("1.22") ؛
System.out.println ("بناء مع قيمة السلسلة:" + a) ؛
BigDecimal B = New BigDecimal ("2.22") ؛
A.Add (B) ؛
System.out.println ("Aplus B IS:" + A) ؛
من السهل التفكير في أنه سوف يخرج:
انسخ الرمز على النحو التالي: بناء مع سلسلة: 1.22
A Plus B هو: 3.44
ولكن في الواقع A Plus B هو: 1.22
4. تحليل رمز المصدر
4.1 طريقة (doubleval) طريقة
انسخ الرمز على النحو التالي: القيمة العليا الثابتة ذات القيمة الكبيرة (مزدوجة Val) {
// تذكير: عوائد مزدوجة صفر "0.0" ، لذلك لا يمكننا أن نكون سريعًا
// لاستخدام الصفر الثابت. قد يكون هذا مهمًا بما يكفي
// تبرير نهج المصنع أو ذاكرة التخزين المؤقت أو عدد قليل من القطاع الخاص
// الثوابت ، لاحقًا.
Returnnew BigDecimal (double.tostring (Val)) ؛ // انظر النقطة الثالثة في 3.1 حول وصف JDK
}
4.2 إضافة طريقة (BigDecimal Augend)
ADD BigDecimal العام (BigDecimal Augend) {long xS = this.intcompact ؛ . ! = تضخيم)؟ null: Augend.Intval ؛ int rscale = this.scale ؛ // الأماكن العشرية الطويلة sdiff = (طويلة) rscale - Augend.scale ؛ // الفرق بين الأماكن العشرية إذا (sdiff! = 0) {// الأماكن العشرية مع معظم الأماكن العشرية هي النتيجة (sdiff <0) rscale = Augend.scale ؛ إذا (xs == تضخيم || (xs = longmultiplypowerten (xs ، رفع)) == مضخمة) fst = bigmultiplypowerten (رفع) ؛ } else {int rise = ugend.checkscale (sdiff) ؛ إذا (ys == تضخيم || (ys = longmultiplypowerten (ys ، refe)) == مضخمة) snd = ugend.bigmultiplypowerten (رفع) ؛ }} if (xs! = vertive && ys! = مضخمة) {long sum = xs + ys ؛ if (((sum ^ xs) & (sum ^ ys)))> = 0l) // judge ما إذا كان هناك أي تدفق. إرجاع bigdecimal.valueof (sum ، rcale) ؛ // إرجاع مثيل BigDecimal الذي تم الحصول عليه باستخدام طريقة المصنع الثابت BigDecimal} if (fst == null) fst = biginteger.valueof (xs) ؛ // Biginteger's Static Factory if (snd == null) snd = biginteof (ys) BigInteger sum = fst.add (snd) ؛ Return (fst.signum == snd.signum)؟ bigDecimal جديد (SUM ، تضخيم ، rcale ، 0): جديد bigdecimal (sum ، compactvalfor (sum) ، rcale ، 0) ؛ما سبق هو مجرد تحليل لرمز مصدر الإضافة. الطرح والضرب والتقسيم في الواقع يعيد كائنًا كبيرًا جديدًا. نظرًا لأن BigInteger و BigDecimal غير قابلتين للتغيير ، سيتم إنشاء كائن جديد عند أداء كل خطوة من خطوة التشغيل ، لذلك A.Add (B) ؛ على الرغم من إجراء عملية الإضافة ، لا يحفظ A القيمة بعد عملية الإضافة. يجب أن يكون الاستخدام الصحيح A = A.Add (B) ؛
5. ملخص
(1) تستخدم الحسابات التجارية BigDecimal.
(2) حاول استخدام البنائين مع سلسلة نوع المعلمة.
(3) bigdecimals غير قابلة للتغيير. عند إجراء كل خطوة من خطوة التشغيل ، سيتم إنشاء كائن جديد. لذلك ، عند إجراء الإضافة والطرح والضرب والقسمة ، يجب عليك حفظ القيمة بعد العملية.
(4) غالبًا ما نميل إلى تجاهل بعض تفاصيل التنفيذ لـ JDK الأساسي ، مما يؤدي إلى أخطاء ، لذلك نحن بحاجة إلى إيلاء المزيد من الاهتمام.
المرجع: الطبقة الكبيرة