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);
Related
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'm using the DecimalFormat with HALF_UP rounding mode and I have an escenery where is not working correctly and I don't know why.
DecimalFormat df = new DecimalFormat("#.##");
df.setRoundingMode(RoundingMode.HALF_UP);
float tmp = (float) (0.5 * 1.05);
df.format(tmp);
float mul = Float.parseFloat(df.format(tmp));
The mul variable value I hope have 0.53 value and I received 0.52 value.
I'm using the Java 1.8.0_131.
SOLVED FINAL CODE
BigDecimal mul = new BigDecimal(0.5).multiply(new igDecimal(1.05));
mul = mul.setScale(2, RoundingMode.HALF_UP);
System.out.println(mul);
You are using the float datatype.
This datatype is not able to precisely hold the value 0.525. See this code for making it clear:
float value = (float) (0.5 * 1.05);
DecimalFormat df = new DecimalFormat("#.########################");
System.out.println(df.format(value));
This prints out:
0.5249999761581421
Rounding such a value with the mode RoundingMode.HALF_UP will correctly yield 0.52.
The double value seems to be able to precisely store the value 0.525:
double value = 0.5 * 1.05;
DecimalFormat df = new DecimalFormat("#.########################");
System.out.println(df.format(value));
This will print the expected value:
0.525
Rounding that value with the mode RoundingMode.HALF_UP will now yield 0.53!
Caution: Even the double datatype does not store the value precisely!
Look at #MarkDickinson's comment. The stored value is 0.52500000000000002220446049250313080847263336181640625 which happens to be larger than 0.525 and only rounds by accident to the expected value.
So what to do?
The data types float and double are binary-based, whereas we humans tend to think decimal-based when dealing with numbers. Read the article "What Every Computer Scientist Should Know About Floating-Point Arithmetic" for much more information.
The solution is to use a decimal-based data type, which exists in BigDecimal.
I'm trying to convert some string values in number using DecimalFormat. I try to explain you my problem in a better way:
I have the following method:
private BigDecimal loadBigDecimal(String value){
BigDecimal bigDecimalToReturn = null;
DecimalFormat df = new DecimalFormat("##.###");
bigDecimalToReturn = new BigDecimal(df.parse(value).doubleValue());
return bigDecimalToReturn;
}
Now if I try to run the method:
BigDeciaml dec = myObject.loadBigDecimal("120,11");
The value of dec is 120.1099999999999994315658113919198513031005859375.
Why decimalFormat is changing the scale of my value?
You are doing conversion to double and backwards. That's unnecessary and introduces rounding errors. You should use the following code:
private BigDecimal loadBigDecimal(String value) throws ParseException {
DecimalFormat df = new DecimalFormat("##.###");
df.setParseBigDecimal(true);
return (BigDecimal) df.parse(value);
}
Doubles are only approximations. That is correct for a double. If you want a specific scale, you need to tell it in the BigDecimal constructor.
That is because of the df.parse(value).doubleValue() call. At this point, the value is converted to a double.
double represent plus or minus the sum of powers of 2 (with positive and negative exponents).
One can write 120 as 64+32+16+8.
But one can't write 0.11 as a finite sum of power of 2.
So there is an approximation.
0.1099999999999994315658113919198513031005859375
Which is a sum of power of 2.
It's look like BigDecimal as a constructor with a string for parameter. Maybe you can just use it.
BigDecimal dec = new BigDecimal("120,11");
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,
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