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.
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.
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)
This bit of code
DecimalFormat formatter = new DecimalFormat("0.00");
return formatter.format(-0.001);
returns
"-0.00"
I would really prefer (and expect) "0.00"
I know I can fix this by writing a subclass of DecimalFormat, but is there a way to do this using the standard DecimalFormat?
EDIT: I only wan't to change the particular case where the result is "-0.00". All other negative values should remain unchanged, eg: -9.1 -> "-9.10"
You could test the string when it's returned.
I don't believe formatting will manipulate the value.
It can only format it. Perhaps you can round it first, and then format it?
DecimalFormat formatter = new DecimalFormat("0.00");
double x = -0.001;
double y = Math.round(x*100.0)/100.0;
return formatter.format(y);
I am having problems using DecimalFormat when I am going to print out coefficients after a regression.
Here is the part of the code that is facing problems;
DecimalFormat twoDForm = new DecimalFormat("0.00");
private double s(double d){
return Double.valueOf(twoDForm.format(d));
}
and here is the error message in eclipse;
Exception in thread "main" java.lang.NumberFormatException: For input string: "0,16"
at sun.misc.FloatingDecimal.readJavaFormatString(Unknown Source)
at java.lang.Double.valueOf(Unknown Source)
at model.ARF2.s(ARF2.java:126)
at model.ARF2.printBestModel(ARF2.java:114)
at testing.testclass3.bestForecastingModel(testclass3.java:69)
at testing.testclass3.main(testclass3.java:36)
Please let me know if anyone has any surgestions on how to fix the code. I want two decimals on my coefficients.
Thank you
Lars
use:
DecimalFormat twoDForm = new DecimalFormat("#.##");
DecimalFormatSymbols dfs = new DecimalFormatSymbols();
dfs.setDecimalSeparator('.');
twoDForm.setDecimalFormatSymbols(dfs);
http://download.oracle.com/javase/1.4.2/docs/api/java/text/DecimalFormat.html
The following excerpt appears to be part of your problem:
To obtain a NumberFormat for a
specific locale, including the default
locale, call one of NumberFormat's
factory methods, such as
getInstance(). In general, do not call
the DecimalFormat constructors
directly, since the NumberFormat
factory methods may return subclasses
other than DecimalFormat. If you need
to customize the format object, do
something like this:
NumberFormat f = NumberFormat.getInstance(loc);
if (f instanceof DecimalFormat) {
((DecimalFormat) f).setDecimalSeparatorAlwaysShown(true);
}
You may want to use the applyPattern method:
applyPattern
public void applyPattern(String
pattern) Apply the given pattern to
this Format object. A pattern is a
short-hand specification for the
various formatting properties. These
properties can also be changed
individually through the various
setter methods. There is no limit to
integer digits are set by this
routine, since that is the typical
end-user desire; use setMaximumInteger
if you want to set a real value. For
negative numbers, use a second
pattern, separated by a semicolon
Example "#,#00.0#" -> 1,234.56
This means a minimum of 2 integer
digits, 1 fraction digit, and a
maximum of 2 fraction digits.
Example: "#,#00.0#;(#,#00.0#)" for
negatives in parentheses.
In negative patterns, the minimum and
maximum counts are ignored; these are
presumed to be set in the positive
pattern.
Throws: NullPointerException - if
pattern is null
IllegalArgumentException - if the
given pattern is invalid.
You are encountering an i18n issue. DecimalFormat is using your default locale which specifies the decimal separator as ,. However, the Double.valueOf does not use the locale. It always expects that the decimal separator is ..
If you want to parse a string formatted with DecimalFormat then you need to use DecimalFormat.parse
I think what you intended to do is:
private static String s(double d) {
return twoDForm.format(d);
}
Are you trying to format the number? Or round it? If you're formatting it, shouldn't your "s" method (bad name IMO, btw, but it's private, so it's your call) return a java.lang.String instead of a double?
Check your Locale.
DecimalFormat twoDForm = new DecimalFormat("0.00");
private double s(double d){
String doubleString = displayNumberAmount(twoDForm.format(d));
return Double.valueOf(doubleString);
}
public static String displayNumberAmount(String amount) {
NumberFormat numberFormat = NumberFormat.getNumberInstance(Locale.CANADA_FRENCH);
Number number = 0;
try {
number = numberFormat.parse(amount);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return String.format(Locale.US, "%1$,.2f", number);
}