java - BigDecimal ضرب بصفر




numerical-analysis rounding-error (2)

لا يمكنك استخدام طريقة equals() لمقارنة BigDecimals ، مثلما يفعل هذا التأكيد. وهذا لأن هذه يساوي وظيفة سوف تقارن الحجم . إذا كان المقياس مختلفًا ، فإن equals() ستظهر كاذبة ، حتى إذا كانت نفس العدد رياضياً.

ومع ذلك ، يمكنك استخدام compareTo() للقيام بما تريد:

كما يشيرassylias ، يجب عليك أيضًا استخدام منشئ BigDecimal new BigDecimal("22.3") لتجنب مشاكل الدقة المزدوجة.

BigDecimal expected = BigDecimal.ZERO;
BigDecimal actual = new BigDecimal("22.3").multiply(BigDecimal.ZERO);
assertEquals(0, expected.compareTo(actual));

هناك أيضًا طريقة تُسمى signum() ، والتي تُرجع 1 أو 0 أو 1 للسلبية والصفر والإيجابية. لذا يمكنك أيضًا اختبار الصفر

assertEquals(0, actual.signum());

أقوم بإجراء عملية الضرب بسيطة مع BigDecimal ولقد وجدت بعض السلوك الغريب عند ضرب من الصفر (ضرب من الصفر هو الصحيح في حالة الاستخدام).

تعلمني الرياضيات الأساسية أن أي شيء مضروب في الصفر سوف يساوي الصفر (انظر: خاصية المنتج الصفري وخصائص الضرب )

ومع ذلك ، ستفشل التعليمة البرمجية التالية باستمرار مع نفس الخطأ:

assertEquals(new BigDecimal(0), new BigDecimal(22.3).multiply(new BigDecimal(0)));
java.lang.AssertionError: 
Expected :0
Actual   :0E-48

هل هذا عدم دقة مع BigDecimal أم أن هناك فرعًا من الرياضيات يفقدني في مكان ما؟

ملاحظات: JDK 1.6.0_27 يعمل في IntelliJ 11


هناك مشكلتان مع شفرتك:

  • يجب عليك مقارنة BigDecimal مع compareTo بدلاً من الأندلس ، كما هو مذكور في الإجابات الأخرى
  • ولكن يجب أيضًا استخدام مُنشئ السلسلة: new BigDecimal("22.3") بدلاً من المُنشئ new BigDecimal(22.3) لتجنب مشكلات الدقة المزدوجة

بمعنى آخر ، التعليمة البرمجية التالية (التي تستخدم بشكل صحيح compareTo) مازال إرجاع false:

BigDecimal bd = new BigDecimal(0.1).multiply(new BigDecimal(10));
System.out.println(bd.compareTo(BigDecimal.ONE) == 0);

لأن 0.1d * 10d != 1







rounding-error