BigDecimal Incorrect Value - java

Does anyone know why BigDecimals in the case below outputs the incorrect result?
double a = 2400;
double b = 3600;
double c = 8;
MathContext mc = new MathContext(14);
BigDecimal aa = new BigDecimal(2400);
BigDecimal bb = new BigDecimal(3600);
BigDecimal cc = new BigDecimal(8);
System.out.println("Doubles: " + (a/b*c));
System.out.println("Big Ds: " + (aa.divide(bb, mc).multiply(cc)));
Output:
Doubles: 5.333333333333333
Big Ds: 5.33333333333336
Thoughts and ideas are welcome.

It is exactly as calculated manually.
2/3: 0.66666666666667
*8: 5.33333333333336
2/3: 0.66666666666667
8 x
----------------
56
48
... +
----------------
*8: 5.33333333333336
This is maybe counter-intuitive to many people's sense of numbers.
But the last 7 has an error of 0.1/3 too much; times 8 becomes 3 rounded up as error, so the last digit becomes 3 + error 3 == 6.
To minimize the rounding error on division:
aa.multiply(cc).divide(bb, mc)
The double calculation uses a precision of around 16 digits, just a bit more that 14.

Related

Splitting and Multiplying double will give me wrong values

I'am trying to multiply A double Variable as time. For example I have 2 hours and 30 minutes. SO the procedure that I have to follow is to multiply 2 with 15 hours for example and then Divide 30 minutes with 60 that is the minutes of the hour and then multiply it with 15. Here is my code:
Double water_time = Double.valueOf(jTextField1.getText());
String[] seperated = String.valueOf(water_time).split("\\.");
int[] intseperated = new int[2];
intseperated[0] = Integer.parseInt(seperated[0]);
intseperated[1] = Integer.parseInt(seperated[1]);
int price1 = intseperated[0] * propertiesFile.multiply_water;
double price2 = (intseperated[1] * propertiesFile.multiply_water) / 60.0D;
double price = (price1 + price2);
My Problem is when iam type 0.10 I get (0.25) that is the correct value but when I type 0.11 I get (2.75) that is wrong. And I cant Understand Why.
I appreciate your time.
Thank you in advance
The issue is in the way you're declaring Double water_time.
0.10 becomes Double 0.1 so then you're actually divide 1 by 4, and get mathematically INCORRECT 0.25
0.11 becomes Double 0.11 as you may expect, and you then divide 11 by 4, and mathematically CORRECT 2.75
To fix - split String first , then turn values as Doubles and calculate accordingly.
Working code:
String[] seperated = jTextField1.getText().split("\\.");
int[] intseperated = new int[2];
intseperated[0] = Integer.parseInt(seperated[0]);
intseperated[1] = Integer.parseInt(seperated[1]);
int price1 = intseperated[0] * propertiesFile.multiply_water;
double price2 = (intseperated[1] * propertiesFile.multiply_water) / 60.0D;
double price = (price1 + price2);
As far as I understood, you want to divide the decimal value by 60 and then multiply of by 15. But what you have done is first multiplied by 15, then divided the whole answer by 60.
double price2 = (intseperated[1] / 60.0D) * propertiesFile.multiply_water;

DecimalFormat is not working properly

I am trying to apply formatting (, after 3 digits and rounding after 4 digits), using below code -
double a = 1231254125412512.231515235346;
NumberFormat formatter = new DecimalFormat("#,###");
formatter.setRoundingMode(RoundingMode.HALF_UP);
formatter.setMinimumFractionDigits(4);
formatter.setMaximumFractionDigits(4);
System.out.println("Number : " + formatter.format(a));
Above code is working properly for the number -54125412512.231515235346 (result was -54,125,412,512.2315).
But it is not working for the number -1231254125412512.231515235346 (result -1,231,254,125,412,512.2000).
Double has a precision of 53 bit which is about 16 digits.
Problem is you use double variable, and and hit max precision Double.MIN_VALUE.
SOURCE:
double: 64 bits (8 bytes) where 52 bits are used for the mantissa (15 to 17 decimal digits, about 16 on average). 11 bits are used for the exponent and 1 bit is the sign bit.
To avoid this problem use BigDecimal instead:
BigDecimal a = new BigDecimal("-54125412512.231515235346");
BigDecimal b = new BigDecimal("-1231254125412512.231515235346");
NumberFormat formatter = new DecimalFormat("#,###");
formatter.setRoundingMode(RoundingMode.HALF_UP);
formatter.setMinimumFractionDigits(4);
formatter.setMaximumFractionDigits(4);
System.out.println("Number : " + formatter.format(a));
System.out.println("Number : " + formatter.format(b));
OUTPUT:
Number : -54.125.412.512,2315
Number : -1.231.254.125.412.512,2315

Issue with rounding aftrer division of BigDecimal values. Java

I've got a problem with the result of division of BigDecimal instances.
My program:
public class DecimalPrecision
public static void main(String[] args) {
MathContext mathContext = new MathContext(25, RoundingMode.HALF_UP);
System.out.println(new BigDecimal("0.1111111111111111111111111").divide(new BigDecimal("3"), mathContext).toString());
}
The result is the following:
0.03703703703703703703703703
But the correct result is:
0.03703703703703703703703704
Basically my program rounded the last digit, which is 7, to 3, not to 4. Why is it so? In mathContext I specified rounding mode HALF_UP. Probably I've got a gap in knowlegde on the issue but I was sure that HALF_UP rounds to a bigger value.
This problem can be sorted out in the next way:
value1 = value1.divide(value2, 10000, RoundingMode.HALF_UP);
return new BigDecimal(value1.toString()).round(mathContext);
But in my taste there's something wrong with parsing the result to a String and then create new properly rounded BigDecimal. I'm asking for your help, how can I resolve this problem without resorting to any strings?
Thanks in advance.
You are starting with a 25 digit number and performing an operation with a precision of 25 digits so you can expect that the last digit might be wrong. The solution is to use more digits than you need and round the result.
BigDecimal oneNinth25 = BigDecimal.ONE.divide(BigDecimal.valueOf(9), 25, BigDecimal.ROUND_HALF_UP);
BigDecimal oneNinth26 = BigDecimal.ONE.divide(BigDecimal.valueOf(9), 26, BigDecimal.ROUND_HALF_UP);
MathContext mathContext = new MathContext(25, RoundingMode.HALF_UP);
System.out.println("1/9 to 25 digits / 3 = " +
oneNinth25.divide(BigDecimal.valueOf(3), mathContext));
System.out.println("1/9 to 26 digits / 3 = " +
oneNinth26.divide(BigDecimal.valueOf(3), mathContext));
prints
1/9 to 25 digits / 3 = 0.03703703703703703703703703
1/9 to 26 digits / 3 = 0.03703703703703703703703704

Extracting the integer and fractional part from Bigdecimal in Java

I want to extract the integer part and decimal part from the bigdecimal in java.
I am using the following code for that.
BigDecimal bd = BigDecimal.valueOf(-1.30)
String textBD = bd.toPlainString();
System.out.println("length = "+textBD.length());
int radixLoc = textBD.indexOf('.');
System.out.println("Fraction "+textBD.substring(0,radixLoc)+"Cents: " + textBD.substring(radixLoc + 1, textBD.length()));
I am getting the output as
-1 and 3
But I want the trailing zero also from -1.30
Output should be -1 and 30
If you like to not get involved with Strings (which I think it's not good practice - except the part of creating de BigDecimal) you could do it just with Math:
// [1] Creating and rounding (just like GriffeyDog suggested) so you can sure scale are 2
BigDecimal bd = new BigDecimal("-1.30").setScale(2, RoundingMode.HALF_UP);
// [2] Fraction part (0.30)
BigDecimal fraction = bd.remainder(BigDecimal.ONE);
// [3] Fraction as integer - move the decimal.
BigDecimal fraction2 = fraction.movePointRight(bd.scale());
// [4] And the Integer part can result of:
BigDecimal natural = bd.subtract(fraction);
// [5] Since the fraction part of 'natural' is just Zeros, you can setScale(0) without worry about rounding
natural = natural.setScale(0);
I know, my english is terrible. Feel free to correct if you could understand what I tried to say. Thanks.
The floating point representation of -1.30 is not exact. Here is a slight modification of your code:
BigDecimal bd = new BigDecimal("-1.30").setScale(2, RoundingMode.HALF_UP);
String textBD = bd.toPlainString();
System.out.println("text version, length = <" + textBD + ">, " + textBD.length());
int radixLoc = textBD.indexOf('.');
System.out.println("Fraction " + textBD.substring(0, radixLoc)
+ ". Cents: " + textBD.substring(radixLoc + 1, textBD.length()));
I have put a RoundingMode on the setScale to round fractional pennies like 1.295 "half up" to 1.30.
The results are:
text version, length = <-1.30>, 5
Fraction -1. Cents: 30
Initialize with a String to avoid problems with floating point accuracy. Then use setScale to set your desired number of decimal places:
BigDecimal bd = new BigDecimal("-1.30").setScale(2);
String textBD = bd.toPlainString();
System.out.println("length = "+textBD.length());
int radixLoc = textBD.indexOf('.');
System.out.println("Fraction "+textBD.substring(0,radixLoc)+"Cents: " + textBD.substring(radixLoc + 1, textBD.length()));

Modulo gives unexpected result

I have some problem with numerator, denumerator and modulo. 7 / 3 = 2.3333333333 gives me a modulo of 1!? Must be some wrong? I study a non-objective ground level course, so my code is simple and I have simplified the code below. (Some lines are in swedish)
Calling the method:
// Anropar metod och presenterar beräkning av ett bråktal utifrån täljare och nämnare
int numerator = 7;
int denumerator = 3;
System.out.println("Bråkberäkning med täljare " + numerator + " och nämnare " + denumerator + " ger " + fraction(numerator,denumerator));
And the method:
// Metod för beräkning av bråktal utifrån täljare och nämnare
public static String fraction(int numerator, int denumerator) {
// Beräkning
int resultat1 = numerator / denumerator;
int resultat2 = numerator % denumerator;
return Integer.toString(resultat1) + " rest " + Integer.toString(resultat2);
}
3 goes into 7 twice with 1 left over. The answer is supposed to be 1. That's what modulo means.
7 modulo 3 gives 1. Since 7 = 2*3 + 1.
7 % 3 = 1
Just as expected. If you want the .3333 you could take the modulo and devide it by your denominator to get 1 / 3 = 0.3333
Or do (7.0 / 3.0) % 1 = 0.3333
Ehm 7 % 3 = 1
What would you expect?
Given two positive numbers, a (the dividend) and n (the divisor), a modulo n (abbreviated as a mod n) can be thought of as the remainder, on division of a by n. For instance, the expression "5 mod 4" would evaluate to 1 because 5 divided by 4 leaves a remainder of 1, while "9 mod 3" would evaluate to 0 because the division of 9 by 3 leaves a remainder of 0; there is nothing to subtract from 9 after multiplying 3 times 3. (Notice that doing the division with a calculator won't show you the result referred to here by this operation, the quotient will be expressed as a decimal.) When either a or n is negative, this naive definition breaks down and programming languages differ in how these values are defined. Although typically performed with a and n both being integers, many computing systems allow other types of numeric operands.
More info : http://en.wikipedia.org/wiki/Modulo_operation
you didn't do a question!
And if your question is just:
"...gives me a modulo of 1!? Must be some wrong?"
No, it isn't, 7/3 = 2, and has a modulo of 1. Since (3 * 2) + 1 = 7.
You are using integer operands so you get an integer result. That's how the language works.
A modulo operator will give you the reminder of a division. Therefore, it is normal that you get the number 1 as a result.
Also, note that you are using integers... 7/3 != 2.3333333333.
One last thing, be careful with that code. A division by zero would make your program crash. ;)
% for ints does not give the decimal fraction but the remainder from the division. Here it is from 6 which is the highest multiplum of 2 lower than your number 7. 7-6 is 1.

Categories