Search code examples
javabigdecimal

Why this comparision between 2 BigDecimal fail?


Into a Java application I have a unit test that contains the following situation:

BigDecimal rendimentoLordoProvvisiorioExpected = new BigDecimal(2.85000);
BigDecimal rendimentoLordoProvvisiorioDB = null;

rendimentoLordoProvvisiorioDB = pucManager.getRendimentoLordoProvvisorio(date);

assertTrue(rendimentoLordoProvvisiorioExpected.compareTo(rendimentoLordoProvvisiorioDB) == 0);

the value of the rendimentoLordoProvvisiorioExpected variable is manually setted to 2.85000 and the obtained value rendimentoLordoProvvisiorioDB is 2.85000.

The problem is that when I do this comparision into the assertTrue() JUnit function

assertTrue(rendimentoLordoProvvisiorioExpected.compareTo(rendimentoLordoProvvisiorioDB) == 0);

it fail because the rendimentoLordoProvvisiorioExpected seems to be 2.850000000000000088817841970012523233890533447265625 and not 2.85000 (as setted).

Why? How can I modify the previous code to set the rendimentoLordoProvvisiorioExpected to the expected value 2.85000?


Solution

  • Because you are initializing the BigDecimal with a floating point value, by calling the constructor with a double. Doubles are floating point numbers. Use a String:

    BigDecimal rendimentoLordoProvvisiorioExpected = new BigDecimal("2.85000");
    

    You should read the documentation of BigDecimal regarding calling the double version of the constructor.

    When you use a BigDecimal, you are converting a base two floating point to a base 10 floating point number. There is no perfect base two floating point representation of the number 2.85, the best approximation seems to be a number close to:

    >>> decimal.Decimal(2.85)
    Decimal('2.850000000000000088817841970012523233890533447265625')
    

    You should read more about floating point, for example What Every Programmer Should Know About Floating-Point Arithmetic.