I am trying to format and save a double using BigDecimal, as I want to use the rounding modes available to it. This code however causes a compilation error:
import java.math.*;
public class Format {
public static void main (String[] args) {
double result = 123.456;
int decimalPlaces = 2;
result = BigDecimal.valueOf(result).setScale(decimalPlaces, RoundingMode.HALF_UP);
System.out.println(result);
}
}
The error encountered:
Format.java:10: error: incompatible types: BigDecimal cannot be converted to double
result = BigDecimal.valueOf(result).setScale(decimalPlaces, RoundingMode.HALF_UP);
The value of result I am looking for is:
123.46
Please help me understand how to correct this.
Edit: I understand that my brevity in asking the question has lead to the question being down voted. It appears as if I encountered a compile error and immediately came to ask for a solution which is not the case. I'll take the time to give clearer exposition next time.
It fails because your variable result is of type double, while operations on a BigDecimal will usually produce values of type BigDecimal. You cannot put a BigDecimal in a variable of type double. You need a variable of type BigDecimal.
Which is what the error message was very clearly telling you, and it is rather concerning that you chose to ignore it and come ask here instead.
The value of result I am looking for is:
123.46
A double is a rather wrong tool for getting to that. doubles are approximate, and you're telling that you want a very exact result and nothing else than that result. Therefore, not an approximation.
If your only goal is to display 123.46 as a result of the number 123.456 you had and that you round to two decimals, then the key word is display. The right tool for displaying text is a String, not a double.
Use a DecimalFormat.
NumberFormat format = new DecimalFormat("0.00");
String s = format.format(result);
System.out.println(s);
No need for BigDecimal.
It might be too obvious, but you cannot assign a double to a BigDecimal.
BigDecimal decimal = BigDecimal.valueOf(result)
.setScale(decimalPlaces, RoundingMode.HALF_UP);
System.out.println(decimal);
Which gives the correct output of 123.46.
If you want a double instead, use BigDecimal.doubleValue().
BigDecimal::setScale return BigDecimal not a double, You have to use BigDecimal::doubleValue() to get the double value, like this :
result = BigDecimal.valueOf(result)
.setScale(decimalPlaces, RoundingMode.HALF_UP)
.doubleValue();
System.out.println(result);// 123.46
setScale() returns a BigDecimal which you are casting to double and hence the error.
https://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html#setScale(int)
Related
I have a BigDecimal defined like this:
private static final BigDecimal sd = new BigDecimal(0.7d);
if i print it, i get the value:
0.6999999999999999555910790149937383830547332763671875
which causes some wrong calculations. Does anyone know a way to get the exact value of 0.7 as BigDecimal? Change it to 0.71 would view the right result, but it shouldn't be like that
Use a String literal:
private static final BigDecimal sd = new BigDecimal("0.7");
If you use a double, actually public BigDecimal(double val) is called. The reason you do not get 0.7 is that it cannot be exactly represented by a double. See the linked JavaDoc for more information.
Perhaps if you bothered to read the documentation, i.e. the javadoc of the constructor you're using, you'd already know the answer.
When a double must be used as a source for a BigDecimal, note that this constructor provides an exact conversion; it does not give the same result as converting the double to a String using the Double.toString(double) method and then using the BigDecimal(String) constructor. To get that result, use the static valueOf(double) method.
When you then look at the javadoc of BigDecimal.valueOf(double), you'll find:
Note: This is generally the preferred way to convert a double (or float) into a BigDecimal, as the value returned is equal to that resulting from constructing a BigDecimal from the result of using Double.toString(double).
So there is your answer: Use BigDecimal.valueOf(0.7d), not new BigDecimal(0.7d).
You should use the declared value in String literal such as new BigDecimal("0.7");
Here are three ways:
private static final BigDecimal sd = new BigDecimal("0.7");
private static final BigDecimal sd = new BigDecimal(0.7d, MathContext.DECIMAL32);
private static final BigDecimal sd = new BigDecimal(0.7d, MathContext.DECIMAL64)
Constructing a BigDecimal from a double is surprisingly complicated. First, it can only be done via the detour of a string. (You can't get the constructor with double and a MathContext right. I've tried a lot. At the latest in cases in which the number of places before the decimal point would need to change due to rounding, it becomes difficult. Hence the warning in the Javadoc that you shouldn’t use it.)
However, even there, it is not enough with a simple String.format(), since String.format() is sensitive to the default Locale and outputs different decimal separators depending on system/VM settings, while the BigDecimal constructor always requires a dot as a decimal separator. So you have to construct your own Formatter with Locale.US. If you have this up and running, you will get a warning of an unclosed resource.
I found this to work:
static BigDecimal toBigDecimal(double value, int decimalPlaces) {
String format = "%." + decimalPlaces + "f";
try (Formatter formatter = new Formatter(Locale.US)) {
String formatted = formatter.format(format, value).toString();
return new BigDecimal(formatted);
}
}
I want to ask how to transform all my String to double with exponential.
when I use the string that length is over seven it's doing fine .
new BigDecimal("12345678").doubleValue() => 1.2345678E7
but seven and under I can't export exponential number.
new BigDecimal("1234567").doubleValue() => 1234567.0
what I want is like 1.234567E6.
Is there any way to do this? I've been searching for a while ,but got nothing.
The problem is the type I return must be double . After transforming the value under seven I can only get the value without exponential.
double test = new BigDecimal("1.234567E6").doubleValue() ;//output 1234567.0
but I need it to be 1.234567E6 and return to caller. Is that Impossible?
You should know that 1.2345678e7 and 12345678.0 are exactly the same value, only with different textual representations. You could represent 1234567.0 as 1.234567e6 too. Also exactly the same double, just a different way of writing it out.
The default output shows values with more than a certain number of significant digits in exponential format ("e-form"), otherwise as plain decimal format.
So you may want to change the formatting of the doubles you receive. This can be done with e.g. DecimalFormat or String.format() or similar. That does not change the doubles, only the way they are presented in a string.
For your problem, you want to convert the value to the BigDecimal with exponential, you can use the DecimalFormat. You can also change the scale for the output value digits.
import java.math.*;
import java.text.*;
public class HelloWorld{
public static void main(String []args){
double a = new BigDecimal("1234567").doubleValue();
String b;
System.out.println(a);
NumberFormat formatter = new DecimalFormat("0.0E0");
formatter.setRoundingMode(RoundingMode.DOWN);
formatter.setMinimumFractionDigits(5); //<---Scale
b = formatter.format(a);
System.out.println(b);
}
}
The output will be like:
1234567.0 //Unformatted Value
1.23456E6 //Formatted Value
See the section about Scientific Notation in java.text.DecimalFormat.
For example,
DecimalFormat scientificFormat = new DecimalFormat("0.###E0");
System.out.println(scientificFormat.format(BigDecimal.valueOf(123456L)));
System.out.println(scientificFormat.format(BigDecimal.valueOf(1234567L)));
scientificFormat.setMinimumFractionDigits(10);
System.out.println(scientificFormat.format(BigDecimal.valueOf(12345678L)));
would give you
1,235E5
1,235E6
1,2345678000E7
Change the pattern to match what you're looking for.
Im adding three big decimals here, but it should give me accurate answer. I'm having two strings here and then converting to big decimal. Please dont ask why Im using strings. There is some business where I will get these values as string then I need to convert. Please find the code
BigDecimal a= new BigDecimal(100.05); --> This value I receive from web service. Its a decimal value from the service.
String b= "100.05";
String c= "200.03";
System.out.println(a.add(new BigDecimal(b).add(new BigDecimal(c))));
Output it gives
400.1299999999999971578290569595992565155029296875
Where as it should be 400.13
The problem is your use of new BigDecimal(100.05). The value of a is then 100.0499999999999971578290569595992565155029296875.
If you had specified that value as a string instead, all would be well:
BigDecimal a = new BigDecimal("100.05");
String b = "100.05";
String c = "200.03";
System.out.println(a.add(new BigDecimal(b).add(new BigDecimal(c))));
// Output: 400.13
If you only have the input as a double, you can use BigDecimal.valueOf(double) instead of calling the constructor:
BigDecimal a = BigDecimal.valueOf(100.05); // a is now exactly 100.05
Compare the BigDecimal(double) documentation:
Translates a double into a BigDecimal which is the exact decimal representation of the double's binary floating-point value. (...)
With that of BigDecimal.valueOf(Double):
Translates a double into a BigDecimal, using the double's canonical string representation provided by the Double.toString(double) method.
Note: This is generally the preferred way to convert a double (or float) into a BigDecimal, as the value returned is equal to that resulting from constructing a BigDecimal from the result of using Double.toString(double).
new BigDecimal(100.05)
This gives 100.0499999999999971578290569595992565155029296875, because 100.05 cannot be represented exactly as a double.
You have to use string here as well:
new BigDecimal("100.05")
As you get this value from a web-service, you probably convert it from a String to a float/double. If this is the case, just skip that conversion step.
If your web-service stub maps the return value to float/double, you can consider mapping it to a String directly and then feed it to BigDecimal constructor, like this:
double v = 100.05; // Value from web service
BigDecimal a= new BigDecimal(String.valueOf(v));
String b= "100.05";
String c= "200.03";
System.out.println(a.add(new BigDecimal(b).add(new BigDecimal(c))));
Live Example
That works because the string will only contain as many digits as are needed to differentiate the almost-100.05 value from the next value on either side that can be represented, and so we get the string "100.05", which then BigDecimal can process correctly.
You can format the answer to Decimal places using String.format and specifiying how many digits.
System.out.println(String.format("%.2f", a.add(new BigDecimal(b).add(new BigDecimal(c)))));
I have to create a love calculator object for my computer science class.
However, every time I compile and run the program I keep ending up with the error:
java.lang.NumberFormatException:
For input string: "70.78%" (in sun.misc.FloatingDecimal)
My code for the method:
public double calculate()
{
double value1;
double value2;
double sqrt1;
double sqrt2;
double relationship;
sqrt1 = Math.sqrt(name1.length());
sqrt2 = Math.sqrt(name2.length());
value1 = (Math.pow(name1.length(), 3)/(Math.random()+0.1))* sqrt1;
value2 = (Math.pow(name2.length(), 3)/(Math.random()+0.1))* sqrt2;
if(value1 > value2)
{
relationship = value2 / value1;
}
else
{
relationship = value1 / value2;
}
NumberFormat nf = NumberFormat.getPercentInstance();
nf.setMinimumFractionDigits(2);
return Double.parseDouble(nf.format(relationship));
}
I attempted to convert it to a float. I tried to separate it by declaring and initializing another double variable and returning that instead but they didn't work. I looked up solutions and most said to use a try and catch but I don't understand how that would work (since I just began the class and am a beginner).
How would I use a try and catch for this situation?
NumberFormat is meant to create a human readable string. 70.78% isn't a number. 70.78 is, but with the percent sign, it's a string. It seems like what you're trying to do is use the number formatting functionality to round the number. This question has some suggestions for how to properly round a number and keep it as a number.
To answer your other question, the proper way to use a try/catch would be like this:
double result;
try{
result = Double.parseDouble(nf.format(relationship));
}catch(NumberFormatException e){
e.printStackTrace();
result = 0.0;
}
return result;
But the only thing that will do is cause your program to not crash and you'll always get 0.0 returned from the calculate() method. Instead you need to fix the source of the exception.
As you see the exception stacktrace, the exception is caused by string 70.78%. This is because it has a symbol where Double.parseDouble() is expecting a string in format of double value representation like 70.78. If you are looking for an output like 70.78% and if the value is correct, you may return nf.format(relationship) and change your return type of calculate to String.
Update
The following values are valid to be parsed as double: "1.2", "1", ".2", "0.2", "1.2D", "1.", to say a valid number representation holdable by the datatype.
I have this code:
public double theInterest(){
return (accountBalance*i) +accountBalance;
My question is, is there a way I can impose DecimalFormat to the result of the equation so that it will display up to 2 decimal places?
Any help is really appreciated.
Your question is as posted nonanswerable since the method returns a double, and DecimalFormat can only return a String. It makes no sense to try to return a formatted double. I don't recommend that you change the method, but consider creating a separate method, say getInterestString() that takes the result of theInterest(), and formats it with your DecimalFormatter and then returns this formatted String.
i.e.,
public String getInterestString() {
NumberFormat moneyFormat = NumberFormat.getCurrencyInstance();
return moneyFormat.format(theInterest();
}
Or more generally,
private NumberFormat moneyFormat = NumberFormat.getCurrencyInstance();
public String currencyFormat(double numberValue) {
moneyFormat.format(numberValue);
}
Edit: and as svc well states, you should strive to avoid using floating point numbers for monetary calculations as the inaccuracies matter. Better to use BigDecimal.
You should not use double at all for financial work. Typically, you use a BigDecimal where your numbers are valued by the lowest currency unit for your country:
BigDecimal tenDollars = new BigDecimal(1000L, 2);
// Alternatively, use the BigDecimal(BigInteger, int) constructor.
You can set the rounding mode by using MathContexts. Internally, you store the BigDecimal for your currency values; only when you display to the user do you convert to a string using a format.