I'm not sure if I'm doing this right.
I'm doing scientific calculations that need to be accurate as possible so I am converting the existing use of Double to BigDecimal.
// before
double tmp = x - (y / z);
// after
BigDecimal tmp = new BigDecimal(
x.value().subtract(y.value().divide(z.value())).toString());
Is this logical or what?
You are doing your arithmetics with doubles before converting the result to BigDecimal. That way you don't gain any precision.
You should convert every number to BigDecimal as soon as possible and then use the methods of BigDecimals (subtract, divide and so on) on the BigDecimal representation to do the arithmetics.
BigDecimal bdX = new BigDecimal(x);
BigDecimal bdY = new BigDecimal(y);
BigDecimal bdZ = new BigDecimal(z);
BigDecimal tmp = bdX.subtract(bdY.divide(bdZ));
BigDecimal has methods for all the operators. You should use them instead. You can also control (specify) the scale and rounding.
Avoid using doulbles, instead use BigDecimal from the beginning.
Assuming that x, y and z are doubles
BigDecimal tmp = new BigDecimal(x).subtract(
new BigDecimal(y).divide(new BigDecimal(z), MathContext.DECIMAL64));
see BigDecimal.divide API to understand why to use MathContext
Related
I have int value 40959999. How to convert it to float without rounding into 409599,99?
result of float f = 40959999/100.00f will be 409600.0
Use double instead of float
double d = 40959999/100.00f;
Double and Float have inherent imprecision that is impossible to avoid (more info on the why here). Using a double you may not have your number rounded in this scenario but not in all. If you work with something that should never be rounded (like prices), you should be using BigDecimal instead.
Implement your int value like shown. Rather than using float use BigDecimal instead.
BigInteger b1 = BigInteger.valueOf(40959999);
int scale = 2;
BigDecimal d1 = new BigDecimal(b1, scale);
System.out.println(d1);
run:
409599.99
I've been trying to sum up decimal values using double in java and it doesn't work well, got a wrong answer.
I've already tried with Double, Float, BigDecimal.
{
double a = 2595.00;
double b = -1760.76;
double c = -834.00;
double d = -.24;
System.out.print(a+b+c+d);
}
The expected result should be "0" But Got 9.1038288019262836314737796783447265625E-15
You can use BigDecimal for this purpose and make sure you input the numbers as String in the BigDecimal constructor:
BigDecimal a = new BigDecimal("2595.00");
BigDecimal b = new BigDecimal("-1760.76");
BigDecimal c = new BigDecimal("-834.00");
BigDecimal d = new BigDecimal("-.24");
System.out.println(a.add(b).add(c).add(d));
Live Example
Output is:
0.00
From the Java docs for BigDecimal(String):
This is generally the preferred way to convert a float or double into
a BigDecimal, as it doesn't suffer from the unpredictability of the
BigDecimal(double) constructor.
Check this SO thread for why double results in a loss of precision.
As already pointed by the previous answers about double precision, the value here is very close to zero. You can see it with System.out.format as well.
System.out.format("%.14f%n",a+b+c+d);
System.out.format("%1.1f%n",a+b+c+d); //to print 0.0
I want to substract 2 double values, and I have tried the following code.
double val1 = 2.0;
double val2 = 1.10;
System.out.println(val1 - val2);
and I got the output as,
0.8999999999999999
For getting output as 0.9 I tried with BigDecimal as follows,
BigDecimal val1BD = new BigDecimal(val1);
BigDecimal val2BD = new BigDecimal(val2);
System.out.println(val1BD.subtract(val2BD));
And I got the output as,
0.899999999999999911182158029987476766109466552734375
Then I tried with BigDecimal.valueOf()
val1BD = BigDecimal.valueOf(val1);
val2BD = BigDecimal.valueOf(val2);
System.out.println(val1BD.subtract(val2BD));
And finally I got the output as 0.9.
My question is what is the difference between case 2 & case 3?
In case 2 why I got the output like that?
BigDecimal.valueOf(double d) uses canonical String representation of double value, internally Double.toString(double) is used, that's why you are getting 0.9 in second case.
Note: This is generally the preferred way to convert a double (or
float) into a BigDecimal, as the value returned is equal to that
resulting from constructing a BigDecimal from the result of using
Double.toString(double).
While with new BigDecimal(0.9) it converts value to exact floating point representation of double value without using String representation,
Translates a double into a BigDecimal which is the exact decimal
representation of the double's binary floating-point value.
...
NOTES :
The results of this constructor can be somewhat unpredictable.
...
FOR EXAMPLE :
BigDecimal bd1 = new BigDecimal(Double.toString(0.9));
BigDecimal bd2 = new BigDecimal(0.9);
System.out.println(bd1);
System.out.println(bd2);
OUTPUT :
0.9
0.90000000000000002220446049250313080847263336181640625
Just for those others that got here looking for some other issue with BigDecimal(not related to the question above)...
remember to give a mathContext to the methods to avoid certain problems e.g.
MathContext mc = new MathContext(10, RoundingMode.HALF_UP);
BigDecimal hitRate = new BigDecimal(totalGetValuesHitted).divide(new BigDecimal(totalGetValuesRequested), mc);
BigDecimal missRate = new BigDecimal(1.0, mc).subtract(hitRate, mc);
I have below code:
Double a = new Double((123456798/1000000)); //123456798 this value comes from client side as a `int`
DecimalFormat df = new DecimalFormat("###.###");
log.info("a :"+a+" df "+df.format(a.doubleValue()));
output:
a :123.0 df 123
//i want output like this, a :123.xxx fd 123.xxx
please help
UPDATE:
123456798 this value comes from client side as a int so i cant do it as 123456798.0 (or something)
123456798 and 1000000 are int literals, so dividing them will use integer arithmetic, and yield 123.
Instead, you could use floating point literals in order to use floating point arithmetic:
Double a = new Double((123456798.0/1000000.0));
DecimalFormat df = new DecimalFormat("###.###");
log.info("a :"+a+" df "+df.format(a.doubleValue()));
Any one value in the division should be float or double.
Double a = new Double((123456798.0/1000000));
or
Double a = new Double((123456798/1000000.0));
if you are getting these values in variables, then multiply it with 1.0
like
Double a = new Double((variable*1.0/1000000));
Put it like that
Double a = new Double((123456798.0/1000000.0)); // <- note ".0"
the reason of the misbehavior is the integer division:
123456798/1000000
is the integer value, while
123456798.0/1000000.0
is the floating point one (double)
Double a = new Double((123456798/1000000));
You are doing integer division here. Make one of the constants a double, so that floating-point division is done. Also, why are you using Double? It's better to use the primitive type double.
double a = 123456798.0 / 1000000;
Or simply, since they are constants:
double a = 123.456789;
You perform an integer division, thats why a is incorrect:
Double a = new Double(123456798.0/1000000);
I have Float value like 0.152545 I just want 0.1f.
How this is possible..
By using String I was get the String value.The following code show the result.
String pass = pass.substring(0, Math.min(pass.length(), 3));
pass=pass+"f";
This gives me String value like0.1f ,But I want only Float value like 0.1f.
It would be appropriate place where you should use DecimalFormat, And .#f would be pattern for your case.
Find more on Number formatting in java.
Some related question -
Show only two digit after decimal.
Formatting numbers using DecimalFormat
You could use a BigDecimal.
float f = 0.152545f;
BigDecimal bd = new BigDecimal(f);
bd = bd.setScale(1, RoundingMode.DOWN);
f = bd.floatValue();
Works fine even if you have a float stored as a String.
String floatAsString = "0.152545";
BigDecimal bd = new BigDecimal(floatAsString);
bd = bd.setScale(1, RoundingMode.DOWN);
float f = bd.floatValue();
You could do:
DecimalFormat format = new DecimalFormat("0.0");
format.setRoundingMode(RoundingMode.DOWN);
format.setMaximumFractionDigits(1);
System.out.println(format.format(0.152545) + "f");
How about
float new = Math.round( 10.0 * f ) / 10.0;
It won't be precise, as floats/doubles are just sums of finite series of 1/2^n, but might be good enough for you.
Perhaps you should be thinking about presenting the float with one significant decimal point and keep full precision internally?
Cheers,