Java new BigDecimal generates another number [duplicate] - java

This question already has answers here:
Format of BigDecimal number
(4 answers)
How do I format a number in Java?
(9 answers)
Is floating point math broken?
(31 answers)
Closed 3 years ago.
I'm using BigDecimal data type, when I set
new BigDecimal(21.30);
then, I returned it as xml source, it shows as
21.30000000000710522735760100185871124467578125
Another number
new BigDecimal(23.11)
returned
23.1099999994315658113818187512921995859375
I want to show results with the same decimals as I set on create.

The results of this constructor can be somewhat unpredictable. One
might assume that writing new BigDecimal(0.1) in Java creates
a BigDecimal which is exactly equal to 0.1 (an unscaled value of 1, with a scale of 1), but it is actually equal to 0.1000000000000000055511151231257827021181583404541015625.
This is because 0.1 cannot be represented exactly as a double (or, for that matter, as a binary fraction of any finite length). Thus, the value that is being passed in to the constructor is not exactly equal to 0.1,
appearances notwithstanding.
If you check the BigDecimal java doc you will find out that you will have to use the constructor which takes a String parameter to end up with the behavior you need.

Related

Java - Rounding 99999999999999.9999 [duplicate]

This question already has answers here:
The accuracy of a double in general programming and Java
(2 answers)
Closed 2 years ago.
I am trying rounding and format techniques in Java as I have to keep my values in database with some specific formats.
My database column has the data precision of 18,4 which means 14 integers and 4 decimal places at max.
Now I am trying max possible value case which is 99999999999999.9999. When I execute the below code, I am getting a rounded value of 1000000000000000. However, I want to store the exact value provided.
Can anyone suggest to keep it as it is in java variable?
DecimalFormat df2 = new DecimalFormat( "#.####" );
df2.setRoundingMode(RoundingMode.CEILING);
double number = Double.parseDouble("99999999999999.9999");
System.out.println("Format: " + df2.format(number));
You can use BigDecimal
BigDecimal number = new BigDecimal("99999999999999.9999");

BigDecimal#compareTo with different scales [duplicate]

This question already has answers here:
new BigDecimal(double) vs new BigDecimal(String) [duplicate]
(4 answers)
Closed 4 years ago.
Why does the following return 1?
new BigDecimal(0.82).setScale(5, BigDecimal.ROUND_HALF_DOWN)
.compareTo(new BigDecimal(0.82))
I expect this to return 0 because BigDecimal.compareTo ignores scale according to its documentation:
Compares this BigDecimal with the specified BigDecimal. Two BigDecimal objects that are equal in value but have a different scale (like 2.0 and 2.00) are considered equal by this method. [...]
new BigDecimal(0.82) is not actually 0.82, because you're passing a double value -- the double closest to 0.82, which is not exactly 0.82 -- to the constructor, so new BigDecimal(0.82) is a BigDecimal equal to the double closest to 0.82.
Instead, use new BigDecimal("0.82").
The problem is that you use the constructor BigDecimal#BigDecimal(double). It returns a BigDecimal that represents the double's binary floating-point value (see its documentation). However, 0.82 isn't representing the value 0.82 but
0.81999999999999995115018691649311222136020660400390625
Because of that .setScale(5, BigDecimal.ROUND_HALF_DOWN) actually changes the value, not only the scale. The resulting value after applying the method is
0.82000
The compareTo method ignores the scale but not different values. As explained, your two BigDecimal actually represent different values. Thus the compareTo does not return 0:
0.82000 != 0.81999999999999995115018691649311222136020660400390625
See the documentation of the method:
Two BigDecimal objects that are equal in value but have a different scale (like 2.0 and 2.00) are considered equal by this method. [...]

Java double calculation problems [duplicate]

This question already has answers here:
Integer division: How do you produce a double?
(11 answers)
Closed 6 years ago.
I'm currently working on a Trafficsimulation which is based on a grid system. For some reason the line of code, which calculates how many tiles i have to add always returns 0. I have tried it without the variables but it still doesn't work.
double blocksToAdd = o.getVelocity()*((1000/Main.FPS)/1000);
Currently the velocity is equal to 1.0f and the Simulation runs at 10 FPS, so blocksToAdd should be 0.1, but it always returns 0.
Since Main.FPS is an int, 1000/Main.FPS is also an int, equal to 100. You then proceed to calculate 100/1000. Since this is an integer division, only the "whole" part is taken, giving 0.
Using floating point literals will cause Java to use floating point division, which should produce the correct result:
double blocksToAdd = o.getVelocity() * ((1000.0 /Main.FPS ) / 1000.0);
// Here --------------------------------------^--------------------^
Most likely due to integer division tuncating the fraction.
Replace the first 1000 with 1000.0 and all will be well. (The latter is a floating point double literal which causes the division to be computed in floating point.) There are other remedies but I find this one to be the clearest.

Rounding to a fixed relative precision [duplicate]

This question already has answers here:
How to round a number to n decimal places in Java
(39 answers)
Round a double to 3 significant figures
(7 answers)
Closed 12 months ago.
I get number representing strings like
248.03500000066338
313.44999999979470
4.2346999999
and I need to round them to something like
248.035
313.45
4.2347
while keeping a fixed relative precision of let's say 6 significant figures. I could do it using Math.log10, computing what absolute precision is needed, and rounding correspondingly, but I wonder if there's a simple way.
Ideally, the resulting number should be such that it does not produce the trailing nines when converted to string, but this is not needed and maybe impossible.
It might not be the most performant solution but I think this is the easiest one:
BigDecimal input = new BigDecimal("248.03500000066338");
double rounded = input.round(new MathContext(6)).doubleValue();

Double data type not returning desired output in java [duplicate]

This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 8 years ago.
In Java, for the following code
Double d = 2.0-1.1;
System.out.println(d);
The result is
0.8999999999999999
If the program is dealing with sensitive information such as precentile/money or cents how do I solve this problem?
I also tried the following piece of code:
new BigDecimal(d)
which outputs
0.899999999999999911182158029987476766109466552734375
What should I do to get 0.90 for the above case?
Since double cannot accurately represent the result of 2 - 1.11, the precision has already been lost by the time the constructor is used.Therefore you need to chain BigDecimal using the String based constructor
BigDecimal result = new BigDecimal("2").subtract(new BigDecimal("1.1"));
The Standard Reference is What Every Computer Scientist Should Know About Floating-Point Arithmetic
A more digestable read: Floating Point Numbers

Categories