I would like to know why I get this error. (this is Display log of Eclipse debug)
var
(double) 2.8
tot.getIva()
(java.lang.Double) 0.17
var+tot.get()
(double) 2.9699999999999998
I can not understand why I did not get simply 2.97!
If you wanted 2.97, you should have used BigDecimal.
doubles are stored as fractions in binary, not decimal. So 3.75, for example, is just stored as 2^1 + 2^0 + 2^(-1) + 2^(-2).
2.8 and 0.17 cannot be represented exactly as binary fractions, so there's going to be some rounding error.
You may also find this article helpful.
This is due to the precision of floating point types in java (float and double). If you need indefinite precision you should try using BigDecimal instead of double.
Related
In java
How to roundoff a value(either float, bigdecimal or double) having the following pattern,
(1) If the value is 1.0, i.e., if the decimal is started with zero then this should not rounded off and the value should be the whole number. ie., in this case "1".
(2) If the value is 1.1 i.e., if the decimal place started with number greater than 0, then the whole number should be rounded to the next number. i.e., if 1.1 then it should be 2.
So you want to round anything below 0.1 down to 0 and 0.1 or more to 1.0
long round = Math.round(x + 0.4);
Try this for a start (for float and double)
int rounded = Math.round(x + 0.4);
See https://docs.oracle.com/javase/8/docs/api/java/math/RoundingMode.html. I believe RoundingMode.CEILING is what you want. BigDecimal lets you control the rounding:
new BigDecimal(1.0).setScale(0, RoundingMode.CEILING).doubleValue(); => 1.0
new BigDecimal(1.1).setScale(0, RoundingMode.CEILING).doubleValue(); => 2.0
Guava includes some utility classes for rounding floats and doubles directly with RoundingModes.
DoubleMath.roundToInt(1.0, RoundingMode.CEILING); => 1
DoubleMath.roundToInt(1.1, RoundingMode.CEILING); => 2
Edit: Whoops. I missed the part where rounding 1.01 should result in 1. The other suggested methods are more correct.
Your specification is not entirely clear to me. I understand your question to mean the "ceil" function, that is, 1.01 has to be rounded up, but your question can also be interpreted such that 1.01 has to be rounded down. (If the latter is what you want, look at Peter Lawrey's answer.)
For doubles (and floats) Java provides the standard method Math.ceil(double a) for the ceil function.
For BigDecimal values you can use the setScale method: set the scale to 0 (no decimal fraction) and the rounding mode to RoundingMode.CEILING to specify how to round:
static BigDecimal ceil(BigDecimal a) {
return a.setScale(0, RoundingMode.CEILING);
}
I have occurred in this strange division error in a grails project (But I think grails has little to do with it, is a groovy or java question I think):
If in the groovy console I run this
float money = -1.30
float r = 0.01
println ((money/r).class.name)
println ((money/r).floatValue())
println ((money/r).toString() )
I get this output
java.lang.Double
-130.0
-129.99999813735482
The float division in groovy give me a Double, and this is correct but
why the Double toString() give me a so strange value "-129.99999813735482" and
not the correct "-130.0"?
From the Floating-Point Guide:
Why don’t my numbers, like 0.1 + 0.2 add up to a nice round 0.3, and
instead I get a weird result like 0.30000000000000004?
Because internally, computers use a format (binary floating-point)
that cannot accurately represent a number like 0.1, 0.2 or 0.3 at all.
When the code is compiled or interpreted, your “0.1” is already
rounded to the nearest number in that format, which results in a small
rounding error even before the calculation happens.
Specifically, neither 1.3 nor 0.01 can be accurately represented by a float.
As everyone says, double and float aren't precise enough for what you're trying to do.
One solution is to not use float as your object type, and do:
def money = -1.30
def r = 0.01
println ((money/r).class.name)
println ((money/r).floatValue())
println ((money/r).toString() )
As you can see, Groovy uses BigDecimal, which means the output is:
java.math.BigDecimal
-130.0
-130
By doing the floatValue, you are limiting the precission of the value. So the JVM does a rounding and you get the different value.
And before you say "but 130.0 should be the value calculated because it is the correct one" keep in mind that the computer uses binary format to represent decimal numbers and this causes rounding errors with fractions (try to represent 0.3 in binary to understand why).
I'm doing some large number divisions (long/long to double, and int/int to float).. But I bump, to a problem when the results include the "E". I know we can use NumberFormat to format when displaying, but that's not what I. Just want the result of the divisions to not involve the "E", i.e. just round it up to the closest float/double that fits in the space.
Anybody got an idea?
The internal representation of floating point number does not have a switch for E presence or not (check IEEE-754). So your float/double number is just number (not a number with E or without it).
The only place where you get E is when you print this value out. And while Java uses number formater for printing, so I don't see a point why you don't want to use it here.
System.out.println(new DecimalFormat("#.#####").format(doubleValue));
The general problem that double and float in binary format. It not always possible to convert decimal fraction to binary fraction. For example 0.2 decmal fraction have infinitely many digits in binary (double) format. So whe converted from bynary format to decimal string, it result something like "0.2000000001" what displayed with E. To solve this problem you can use BigDecimal class what contains number in decimal format, so no E problem - it can easy rounded to any decimal point by setScale method. Or you can sore double as is, an write it to output by String.format("My value are: %.3f", value) - i recommend this way.
If you just want round you value to decimal point you can use:
new BigDecimal(val).setScale(3, RoundingMode.HALF_EVEN).doubleValue()
But there no any garanty what this core return double with fine fraction numbers.
Is this a glitch in Java?
I go to solve this expression: 3.1 - 7.1
I get the answer: -3.9999999999999996
What is going on here?
A great explanation can be found here. http://www.ibm.com/developerworks/java/library/j-jtp0114/
Floating point arithmetic is rarely exact. While some numbers, such
as 0.5, can be exactly represented as a binary (base 2) decimal (since
0.5 equals 2-1), other numbers, such as 0.1, cannot be. As a result, floating point operations may result in rounding errors, yielding a
result that is close to -- but not equal to -- the result you might
expect. For example, the simple calculation below results in
2.600000000000001, rather than 2.6:
double s=0;
for (int i=0; i<26; i++)
s += 0.1;
System.out.println(s);
Similarly, multiplying .1*26 yields a result different from that of
adding .1 to itself 26 times. Rounding errors become even more serious
when casting from floating point to integer, because casting to an
integral type discards the non-integral portion, even for calculations
that "look like" they should have integral values. For example, the
following statements:
double d = 29.0 * 0.01;
System.out.println(d);
System.out.println((int) (d * 100));
will produce as output:
0.29
28
which is probably not what you might expect at first.
See the provided reference for more information.
As mentioned by several others you cannot count on double if you would like to get an exact decimal value, e.g. when implementing monetary applications. What you should do instead is to take a closer look at BigDecimal:
BigDecimal a = new BigDecimal("3.1");
BigDecimal b = new BigDecimal("7.1");
BigDecimal result = a.subtract(b);
System.out.println(result); // Prints -4.0
Computers are 100% so in the math world that is correct, to the average person it is not. Java cant have a error on a specific number as it is just code that runs the same way but has a different input!
P.S. Google how to round a number
rounding errors in floating points
same way that 3 * 0.1 != 0.3 (when it's not folded by the compiler at least)
Automatic type promotion is happening and that is the result.
Here is some resource to learn.
http://docs.oracle.com/javase/specs/jls/se5.0/html/conversions.html
The next step would be is to learn to use formatters to format it to the given precision / requirements.
I have the following code, I want to assign a decimal value to float without losing precision.
String s1= "525.880005";
Float f = new Float(s1);
System.out.println(f);
Output:
5.88
Expected Output:
525.880005
Float only has 7-8 significant digits of precision. The "5" in your example is the 9th digit.
Even if it had enough precision, I don't know whether 525.880005 is exactly representable as a binary floating point number. Most decimal values aren't :)
You should use BigDecimal if the exact decimal representation is important to you.
There's a real contradiction implied in the question :
Assign to float <--> wiht precision
525.880005 is jus the number in this float-domain that is closest to 525.88.
The reason that floating numbers cannot be mapped to all numbers is because of the mismatch between the decimal and the binary system for fractions.
Other types, such as decimal and money, use other, much more memory consuming, techniques to store the number (for example , in a string you can store any number, but of course this is not the most performant way to do math)
a simple example : 0.3 in my own binary system :
0.1b (inary) would be 0.5 d (ecimal) so too much...
0.01b --> 0.25d (1/4 too little)
0.011 --> 0.375 (1/4 + 1/8 too much)
0.0101 --> 0.3125 (1/4 + 1/16 still too much)
...
0.010011 --> 1/4 +1/32 + 1/64 = 0.296875
Suppose my system has 6 bits to represent the fraction, 0.296875 would be the closest for this domain. The right number cannot be reached due to the decimal/binary system.
For examples see also :
Floating point inaccuracy examples
And an excellent elaborate explenation of your problems is to be found here:
http://download.oracle.com/docs/cd/E19957-01/806-3568/ncg_goldberg.html
Another note : it is really about mismatch, not about 'quality' of systems : in decimal notation for example, you cannot represent 1/3 100% accurate, while this would be perfectly possible in other systems.
The float type cannot hold every possible value (nor can double). If you're assigning from a string, you may prefer BigDecimal as BigDecimal can precisely hold anything that you can reasonably represent with a string.
Note that BigDecimal also cannot hold every possible value (it can't precisely represent 1/3rd, for instance, for the same reason we can't write 1/3rd precisely in our decimal notation system — it would never end). But again, if your source is a string value, BigDecimal will more closely align with your possible values than will float or double. Of course, there's a cost. float and double are designed to be very fast in computation; BigDecimal is designed to be very precise with decimal values, at the expense of speed.
Float doesn't have enough significant digits to represent your number. Try Double.