Need help with BigDecimal Precision Issue


#1

Hello Team,

I need help with a BigDecimal Value.

The issue is I have a scenario where I am grabbing a price from website in BigDecimal datatype and then verifying if it is equal to my expected value, both the price and expected value are in BigDecimal. The expected value I am calculating is within the script

total_item_wise_after_increment_1 = WebUI.getText(findTestObject('4_Shopping_Cart_Page/Total_Item_Wise')).replace('$', '')

BigDecimal total_item_wise_after_increment = new BigDecimal(total_item_wise_after_increment_1)

WebUI.println('Total for the Item on Shopping Cart Page after increment is : ' + total_item_wise_after_increment)

/* Calculating Expected Total */

expected_total_item_wise_after_increment_1 = total_item_wise.multiply(expected_quantity_shopping_cart_after_increment)

BigDecimal expected_total_item_wise_after_increment = new BigDecimal(expected_total_item_wise_after_increment_1)

WebUI.println('The expected total item wise after increment should be  : ' + expected_total_item_wise_after_increment)

/* The Script will now verify if expected total item wise is equal to what shows up on the Shopping Cart page */

assert expected_total_item_wise_after_increment.equals(total_item_wise_after_increment)

Upon executing the Script I am getting this error :

Assertion failed: 

assert expected_total_item_wise_after_increment.equals(total_item_wise_after_increment)
       |                                        |      |
       |                                        false  242.45
       242.44999999999998863131622783839702606201171875

I tried to Use Rounding method but that doesn’t work all the time, The price will change every time I run the test case.


#2

You should learn about the BigDeciaml’s setScale method.

A tutorial about it:
https://www.tutorialspoint.com/java/math/bigdecimal_setscale_rm_roundingmode.htm


#3

hello,

i tried with RoundingMode.CEILING --> round up if rounding digit is 5 or greater
242.44999999999998863131622783839702606201171875 after changing the scale to 2 and rounding is 242.45

// create 2 BigDecimal Objects
BigDecimal bg1, bg2;
bg1 = new BigDecimal(242.44999999999998863131622783839702606201171875);
// set scale of bg1 to 2 in bg2 using floor as rounding mode
bg2 = bg1.setScale(2, RoundingMode.CEILING);
String str = bg1 + " after changing the scale to 2 and rounding is " +bg2;
// print bg2 value
System.out.println( str );
output
242.45

#4

Are the “expected_quantity_shopping_cart_after_increment” and “total_item_wise” also BigDecimal objects?

Also, you don’t need this line:

BigDecimal expected_total_item_wise_after_increment = new BigDecimal(expected_total_item_wise_after_increment_1)

because the multiply() method from the previous step will return a BigDecimal already.


#5

@Brandon_Hein Yes both are big decimal objects.


#6

The rounding off solution doesn’t work all the time. Here is the scenario

  • If the product price is 48.49 and customer buys 2 quantity then the website shows total_item_wise_after_increment = 96.98

  • To calculate the expected_total_item_wise_after_increment I am doing total_item_wise.multiply(expected_quantity_shopping_cart_after_increment) which is giving 96.99


#7

Executing the below code:

BigDecimal price = new BigDecimal("48.49");
BigDecimal quantity = new BigDecimal("2");
BigDecimal total = price.multiply(quantity);

the value of ‘total’ correctly shows 96.98. While the other comments are correct, you can indeed mess with the rounding strategy, the whole point of using BigDecimal is that you shouldn’t need to worry about it. If you want, you can DM me your code and I can check where the disconnect is.