While converting BigDecimal to double, extra precisions are getting added.
Could you please suggest this.
For Ex:
BigDecimal deci= new BigDecimal(1.23456789123457E+17);
double value = deci.doubleValue();
System.out.println(value);
And value prints - 1.23456789123456992E17. How come the last digit 7 is converted to 6992? Is there is any way I can get the same input which I am passing to BigDecimal after converting to double?
There are useful methods Math.nextUp() and Math.nextDown() which can help you to investigate this issue:
BigDecimal deci= new BigDecimal(1.23456789123457E+17);
double value = deci.doubleValue();
System.out.println(value);
System.out.println(Math.nextDown(value));
System.out.println(Math.nextUp(value));
The output is:
1.23456789123456992E17
1.23456789123456976E17
1.23456789123457008E17
So as you can see, the double number ...456976 is immediately followed by ...456992, which in turn is immediately followed by ...457008. So BigDecimal.doubleValue() should select between two closest numbers ...456992 and ...457008. No other double number exist between them.
Actually you don't even need the BigDecimal for this test:
double value = 1.23456789123457E+17;
System.out.println(value); // prints 1.23456789123456992E17
Related
I want to assign a double value to another variable but only until it's first 2 decimal value.
Suppose I have 3.4586748547 value in a variable but I want to save 3.45 in another variable. How can I do this?
-I am using JAVA
Using BigDecimal (import java.math.BigDecimal;):
BigDecimal input = new BigDecimal(String.valueOf(3.4586748547d));
double output = input.setScale(2, BigDecimal.ROUND_FLOOR).doubleValue();
System.out.println(output);
You can also use regex for that purpose, like below:
String inputString = String.valueOf(3.4586748547d);
String outputString = inputString.replaceAll("(\\d+\\.\\d{2})\\d+", "$1");
System.out.println(outputString);
The fixed point type in Java is BigDecimal.
Floating point is just an approximation, a sum of powers of 2. 3.45 or 3.4499999987 might be the exact same double. But one can round, and when printing with %.2f format will be shown nice. Though the error will be shown when summing or multiplying.
x = Math.round(x * 100) / 100.0;
Unfortunately.
Struggling for hrs on how to print any one of this value in java
double s = 123456789123456789.988;
double r = 123456789123456789.9889012213;
double q = 123456789123456789.988901221344221;
I tried all the methods in java but nothing works.
Please help me.
Thanks
double has from 15 to 17 significant decimal digits precision. Your numbers have 21, 28, and 33 digits, so they get truncated.
Use BigDecimal created from a String to get the desired precision:
BigDecimal s = new BigDecimal("123456789123456789.988");
BigDecimal r = new BigDecimal("123456789123456789.9889012213");
BigDecimal q = new BigDecimal("123456789123456789.988901221344221");
Note that it is impossible for a double to store those values. To see the nearest numbers that a double can store, try this:
double value = 123456789123456789.988;
double lower = Math.nextDown(value);
double higher = Math.nextUp(value);
System.out.println(new BigDecimal(lower)); // 123456789123456768
System.out.println(new BigDecimal(value)); // 123456789123456784
System.out.println(new BigDecimal(higher)); // 123456789123456800
As you can see, even the smallest possible increase in value, is still an increase of 16, so it's not even close to be able to handle the fractional digits.
Double values are great to do super-fast operations, but not so nice to display, you'll get nicer results with BigDecimal, plus, you still can get the double value from BigDecimal, so you'll get the best of the two worlds:
import java.math.BigDecimal;
BigDecimal s = new BigDecimal("123456789123456789.988");
// Print it correctly:
System.out.println( s );
// prints 123456789123456789.988
// Get its double value to do some super fast operation:
double doubleValue = s.doubleValue();
I have code like this:
double priceMulti = 1.2;
double price = Double.parseDouble(jTextField1.getText());
double date = 1980;
double random = Math.random()*20;
jLabel28.setText(priceMulti*String.valueOf(price)*date*random);
and in line with setting text I got an error "bad operand types for binary operator "*""
so I cant multiple anything.
Edit: main question is Solved, but now I want to use BigDecimal, not Doubles, because they are like 1.000012, and I dunno how.
You're trying to multiply a String value with a double value. The arithmetic operators do not work on String values. You need to multiply all the doubles and then get the String value of it to set it to your jLabel28.
jLabel28.setText(String.valueOf(priceMulti * price * date * random));
You cannot multiply string by double in Java. You should do multiplication of all the doubles you have and then cast it to string to set the resulting value into Label text
I want to return a double with 2 decimal places (i.e. 123.00). The following are part of the codes. The output is always 123.0. How to get a two decimal places?
public static double getPrice(){
double price = Double.valueOf(showInputDialog("Stock's price : "));
DecimalFormat rounded = new DecimalFormat("###.00");
double newPrice = Double.valueOf(rounded.format(price));
System.out.println(newPrice);
return newPrice;
}
As long as the return type of your function is double, the short answer is "you can't".
Many numbers that have no more than two decimal digits cannot be represented exactly as double. One common example is 0.1. The double that's nearest to it is 0.100000000000000005551115...
No matter how much rounding you do, you wouldn't be able to get exactly 0.1.
As far as your options go, you could:
accept the rounding issues associated with using double;
return an int (i.e. the rounded value multiplied by 100);
return a String;
return a BigDecimal.
In particular, if you're representing monetary amounts, using double is almost certainly a bad idea.
When formatting, you're making a string from a double. Don't convert your formatted string to a double again :
String formattedPrice = rounded.format(price);
System.out.println(formattedPrice); // prints 123.00 or 123,00, depending on your locale
A double keeps a numerical value following IEEE754, it doesn't keep any formatting information and it's only as precise as the IEEE754 double precision allows. If you need to keep a rendering information like the number of digits after the comma, you need something else, like BigDecimal.
In Java, I want to take a double value and convert it to a BigDecimal and print out its String value to a certain precision.
import java.math.BigDecimal;
public class Main {
public static void main(String[] args) {
double d=-.00012;
System.out.println(d+""); //This prints -1.2E-4
double c=47.48000;
BigDecimal b = new BigDecimal(c);
System.out.println(b.toString());
//This prints 47.47999999999999687361196265555918216705322265625
}
}
It prints this huge thing:
47.47999999999999687361196265555918216705322265625
and not
47.48
The reason I'm doing the BigDecimal conversion is sometimes the double value will contain a lot of decimal places (i.e. -.000012) and the when converting the double to a String will produce scientific notation -1.2E-4. I want to store the String value in non-scientific notation.
I want to have BigDecimal always have two units of precision like this: "47.48". Can BigDecimal restrict precision on conversion to string?
The reason of such behaviour is that the string that is printed is the exact value - probably not what you expected, but that's the real value stored in memory - it's just a limitation of floating point representation.
According to javadoc, BigDecimal(double val) constructor behaviour can be unexpected if you don't take into consideration this limitation:
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.
So in your case, instead of using
double val = 77.48;
new BigDecimal(val);
use
BigDecimal.valueOf(val);
Value that is returned by BigDecimal.valueOf is equal to that resulting from invocation of Double.toString(double).
It prints 47.48000 if you use another MathContext:
BigDecimal b = new BigDecimal(d, MathContext.DECIMAL64);
Just pick the context you need.
You want to try String.format("%f", d), which will print your double in decimal notation. Don't use BigDecimal at all.
Regarding the precision issue: You are first storing 47.48 in the double c, then making a new BigDecimal from that double. The loss of precision is in assigning to c. You could do
BigDecimal b = new BigDecimal("47.48")
to avoid losing any precision.
Why not :
b = b.setScale(2, RoundingMode.HALF_UP);
It's printing out the actual, exact value of the double.
Double.toString(), which converts doubles to Strings, does not print the exact decimal value of the input -- if x is your double value, it prints out exactly enough digits that x is the closest double to the value it printed.
The point is that there is no such double as 47.48 exactly. Doubles store values as binary fractions, not as decimals, so it can't store exact decimal values. (That's what BigDecimal is for!)
The String.format syntax helps us convert doubles and BigDecimals to strings of whatever precision.
This java code:
double dennis = 0.00000008880000d;
System.out.println(dennis);
System.out.println(String.format("%.7f", dennis));
System.out.println(String.format("%.9f", new BigDecimal(dennis)));
System.out.println(String.format("%.19f", new BigDecimal(dennis)));
Prints:
8.88E-8
0.0000001
0.000000089
0.0000000888000000000
BigDecimal b = new BigDecimal(c).setScale(2,BigDecimal.ROUND_HALF_UP);
In Java 9 the following is deprecated:
BigDecimal.valueOf(d).setScale(2, BigDecimal.ROUND_HALF_UP);
instead use:
BigDecimal.valueOf(d).setScale(2, RoundingMode.HALF_UP);
Example:
double d = 47.48111;
System.out.println(BigDecimal.valueOf(d)); //Prints: 47.48111
BigDecimal bigDecimal = BigDecimal.valueOf(d).setScale(2, RoundingMode.HALF_UP);
System.out.println(bigDecimal); //Prints: 47.48