This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 7 years ago.
double x = 0.00090;
double b = 0.00100;
double c = x - b;
produces
-1.0000000000000005E-4
instead of
-0.0001
and
double x = -0.09;
double b = 0.001;
double c = x * b;
produces
-8.999999999999999E-5
instead of
-0.00009
I also tried with
Math.round(c) and Math.round(c*100.0)/100.0
but it is producing same results or results with incomplete number range after decimal.
That's how numeric operations are defined in the specification.
Decimal numbers are internally represented as the closest approximation, which in some cases is not the exact literal value.
If you need precise numeric computation, you have to use BigDecimal.
The answers are correct. You might want to read up on how doubles are stored in binary digits. its because it's base 2. If we used something like base 3, then in normal digits, 2/3 would be 0.66666666... but in the "tridigit" it would be 0.2
The E notation is confusing you (explanation on how it works here)
-1.0000000000000005E-4
is
-0.00010000000000000005
in standard notation and
-8.999999999999999E-5
is
-0.00008999999999999999
in standard notation. All the answer you see are correct (almost, but they are very close, decimal math isn't always precise), just using the E notation.
try this:
double x = 0.00090;
double b = 0.00100;
BigDecimal xd = new BigDecimal(x).setScale(10, RoundingMode.HALF_UP);
BigDecimal bd = new BigDecimal(b).setScale(10, RoundingMode.HALF_UP);
BigDecimal cd = xd.multiply(bd);
double c = cd.doubleValue();
System.out.println(c);
For precise calculations, like money calculations, you should use BigDecimals, because they have desired precision, and don't lost any accuracy.
If you prefer printing without "E", try this line:
System.out.println(cd.toPlainString());
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
This question already has answers here:
How can I divide properly using BigDecimal
(2 answers)
Closed 5 years ago.
The title says it all: How do I divide a BigInteger by a floating point number in Java? I don’t need the fraction part of the division, it is okay to have it either rounded or truncated (however I would be interested which one applies).
The “obvious” does not even compile:
BigInteger x = BigInteger.valueOf(73).pow(42);
BigInteger y = x.divide(Math.PI); // The method divide(BigInteger) in the type BigInteger is
// not applicable for the arguments (double)
System.out.println(y);
I expected this one to work:
BigInteger y = new BigDecimal(x).divide(BigDecimal.valueOf(Math.PI)).toBigInteger();
Unluckily, it gives an ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result. This is true for π, of course…
Of course, this one works, but it is way too slow…
BigInteger y = BigInteger.valueOf(-1);
BigDecimal σ = BigDecimal.ZERO;
while(σ.compareTo(new BigDecimal(x)) < 0) {
y = y.add(BigInteger.ONE);
σ = σ.add(BigDecimal.valueOf(Math.PI));
}
What’s the correct, canonical way?
You have to add RoundingMode to divide function, otherwise java doesn't know how to round the division and gives you ArithmeticException
BigInteger y = new BigDecimal(y).divide(BigDecimal.valueOf(Math.PI), RoundingMode.HALF_UP).toBigInteger();
All Rounding types are well explained in the documentation link above.
This question already has answers here:
fixed point arithmetics in java with fast performance
(4 answers)
Closed 7 years ago.
I have two double variables:
double a = 1.109
double b = 5.0E-5;
But b is changable and I want to achieve fixed numbers of decimal places depending of b number, for example above I want achieve this result:
Result = 1.10900
But not only print, I need to send it to other method and my double must have fixed numbers of decimal places like in example.
It sounds like you want arbitrary precision on the actual value (as opposed to just output). double doesn't give you that. BigDecimal does though. Its BigDecimal(String) constructor sets the value and the scale (number of places to the right of the decimal) from a string, so:
BigDecimal d = new BigDecimal("1.10900");
BigDecimal then gives you various math operations to stay within that scale, with various rounding options.
If at some point you need to get the double value of the BigDecimal, you can use its doubleValue method. But note that at that point, again, you don't have a fixed number of places to the right of the decimal anymore.
Here's an example contrasting BigDecimal and double (Live Copy):
import java.math.*;
class Example
{
public static void main (String[] args) throws java.lang.Exception
{
BigDecimal bd = new BigDecimal("1.10900");
bd = bd.divide(new BigDecimal("27"), BigDecimal.ROUND_HALF_DOWN);
System.out.println("1.109 / 27 using BigDecimal to five places: " + bd);
double d = 1.109;
d = d / 27.0;
System.out.println("1.109 / 27 using double: " + d);
}
}
Output:
1.109 / 27 using BigDecimal to five places: 0.04107
1.109 / 27 using double: 0.041074074074074075
Try using a number formatter:
NumberFormat formatter = new DecimalFormat("#0.00000");
double a = 1.109;
double b = 5.0E-5;
System.out.println(a);
System.out.println(b);
Output:
1.10900
0.00005
A simple solution is to round the result as needed. This is not only faster than using BigDecimal it can be less error prone as Java doesn't have language support for BigDecimal making it harder to write/read and validate. A simple method for rounding half up for 5 decimal spaces is
public static double round5(double d) {
final double factor = 1e5;
return d > Long.MAX_VALUE / factor || d < -Long.MAX_VALUE / factor ? d :
(long) (d < 0 ? d * factor - 0.5 : d * factor + 0.5) / factor;
}
Note: when you print the double you will still need to specify the number of decimal places you need e.g.
System.out.printf("%.5f", value);
Use java printf-like routine (note it produces platform dependent decimal separators):
String.format("%.5f", a)
This question already has answers here:
How to multiply a BigDecimal by an integer in Java
(3 answers)
Closed 8 years ago.
I have one value like 0.0004 when I store this in Integer it is converting into Exponential format, So I have used Bigdecimal to convert it to normal value like below
Bigdecimal x=BigDecimal.valueOf(0.0004)
Now I am trying to multiply as x*100 but I am getting below error.
Error: The operator * is undefined for the argument type(s) BigDecimal, int
Because of this error if I use this without bigdecimal again it is converting to EXponential.
Can any one please suggest me the way to multiply Bigdecimal and int.
googled a lot but couldn't find the correct solution.
Thanks for your time
You can use BigDecimal.multiply to multiply your BigDecimal.
However, the int value of 0.0004 * 100 will be 0, which is probably not what you want.
Finally, you can alter the how the BigDecimal is represented in terms of fractional digits by using a NumberFormat instance and formatting your Number.
Here's an example:
BigDecimal x= BigDecimal.valueOf(0.0004);
BigDecimal y = x.multiply(new BigDecimal("100"));
int z = y.intValue();
System.out.printf("y is %s\tz is %d%n", y, z);
// edit to truncate fractional digits
NumberFormat nf = NumberFormat.getInstance();
nf.setMaximumFractionDigits(2);
System.out.printf("y (2 fraction digits) is %s", nf.format(y));
Output
y is 0.04000 z is 0
y (2 fraction digits) is 0.04
BigDecimal's are objects. They don't have normal operators.
Instead of a normal multiplication operator like x*10, you need to call the method multiply in BigDecimal:
x = x.multiply(new BigDecimal(10));
If you want to store it in a new value:
BigDecimal n = x.multiply(new BigDecimal(10));
And to convert that to a primative:
double d = n.doubleValue();
int i = n.intValue();
However, if you're trying to use decimals, why not just use a double:
double x = 0.0004;
double n = x*100;
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why does (360 / 24) / 60 = 0 … in Java
Having problems with floats and longs in Java
float f = 0.100f;
f = 3/180;
At the minute i am trying to do something like this with object and their attributes, but even to this simplest form my program returns 0.0.
I have tried this with Longs as well as still the same result. It's been a long day and maybe it's something simple but I'm at a brick wall.
Your expression 3/180 is performing an integer division, and it is then casting that into the float f. In integer division, 3/180 will return 0, and this is what you are seeing.
What you probably want to do is just add a decimal point to your numbers: f = 3.0/180.0;
3/180 is integer division.
Therefore, the result is truncated to an integer.
You need to perform floating-point division: 3/180f
You do an integer division. So you get an int which is casted back to a float. Try this:
f = 3/180.0;
or
f = 3/180f;
Try 3.0/180. Otherwise, you are dividing two integers and you run into integer truncation. When you do integer division the result is also an integer, not a floating point number.