Why Is Bigdecimal Returning a Weird Value

Why is BigDecimal returning a weird value?

You are right, BigDecimal should be storing it correctly, my best guess is:

  • BigDecimal is storing the value correctly
  • When passed to a string formatting function, BigDecimal is being cast as a lower precision floating point value, creating the ...02.
  • When compared directly with a float, the float has an extra decimal place far beyond the 20 you see (classic floats can't be compared behavoir).

Either way, you are unlikely to get accurate results comparing a float to a BigDecimal.

Java double and bigdecimal same weird value

You're running up against double's limits to accuracy since you're initializing your BigDecimal with a double literal. Instead, consider initializing your BigDecimal with a String literal, not a double literal value:

public static void main(String[] args) {
double x = 2.3333333333312398;
BigDecimal big = BigDecimal.valueOf(2.3333333333312398);
BigDecimal big2 = new BigDecimal("2.3333333333312398");

System.out.println(x);
System.out.println(big);

System.out.println(big2);
}

which returns:

2.3333333333312396
2.3333333333312396
2.3333333333312398

Why this weird output with truncate and BigDecimal?

Floating points are inherently inaccurate by their design. Other answers here already explain the theory behind this inaccuracy. It is highly recommended that you use BigDecimal and BigInteger instead.

In my answer I want to elaborate on how you are using BigDecimal wrongly and how you can use it correctly. Don't make the mistake of simply using these classes as a wrapper for floating point calculations. In your present code:

BigDecimal a = new BigDecimal(d + 0.1);

Even though you are trying to use BigDecimal here, you are still performing the addition using regular floating point calculations. This is exactly the same as doing:

double d_a = d + 0.1; //0.799999999 ad infinitum
BigDecimal a = new BigDecimal(d_a);

To take advantage of the accuracy of the BigX classes, you must use their own calculation methods, as well as the valueOf static method (not the constructor):

BigDecimal a = BigDecimal.valueOf(d).add( BigDecimal.valueOf(0.1) );

Here, two BigDecimal objects are created to match exactly 0.7 and 0.1, then the add method is used to calculate their sum and produce a third BigDecimal object (which will be 0.8 exactly).

Using the valueOf static method instead of the constructor ensures the created BigDecimal object represents the exact double value as it is shown when converted to a string (0.7 as a string is "0.7"), rather than the approximate value stored by the computer to represent it (the computer stores 0.7 as 0.699999999 ad infinitum).

Why does BigDecimal return this value after rounding half up?

This is an answer to the literal question

Why does BigDecimal return this value after rounding half up instead
of the expected value and how can i reach this?

applied to 0.4445 rounding to 0.44 rather than "expected" 0.45.

BigDecimal.ROUND_HALF_UP is defined as

Rounding mode to round towards "nearest neighbor" unless both
neighbors are equidistant, in which case round up.

The scale factor two neighbors are 0.44 and 0.45. The absolute difference between 0.4445 and 0.44 is 0.0045. The absolute difference between 0.4445 and 0.45 is 0.0055. The neighbors are not equidistant and 0.44 is the nearest neighbor.

If you really, really want a weird and unnecessarily inaccurate rounding mode, use BigDecimal's toString method to get the full String representation. You can then mangle it any way you like using String operations.

BigDecimal.intValue() returns Unexpected Number

When you try to fit this number into an int variable, it overflows, since the int type in Java has 32 bits, ergo an int variable can store values that range from −2,147,483,648 to 2,147,483,647.

To store the value of your BigInteger, you have to use a long variable. Try this:

long value = d.longValue();

Strange rounding issue with BigDecimal

Don't initialize your BigDecimal with a double. You already have a precision problem when you create your BigDecimal. Use a String instead:

System.out.println( (new BigDecimal("1.340")).round(new MathContext(7, RoundingMode.DOWN))); //returns 1.340
System.out.println( (new BigDecimal("2.340")).round(new MathContext(7, RoundingMode.DOWN))); //returns 2.340

BigDecimal adding wrong value

Use a String literal:

private static final BigDecimal sd = new BigDecimal("0.7");

If you use a double, actually public BigDecimal(double val) is called. The reason you do not get 0.7 is that it cannot be exactly represented by a double. See the linked JavaDoc for more information.

Why does Ruby's BigDecimal represent numbers oddly sometimes?

After looking at the versions, it appears I am running Ruby 1.8.5 on the RHEL box and Ruby 1.8.6 on my local box. I assume this would account for the problems? Strange problems indeed.

Update:
Confirmed - Upgrade to 1.8.6 resolved the issues.



Related Topics



Leave a reply



Submit