I have a String which is like "$1,234.00". I need to convert it into a BigDecimal value. Cannot do it utilising normal BigDecimal conversion methods as it throws NumberFormatException. Is there a way it can be achieved?
"$1,234.00" is a formatted numeric text, so you need to parse the number using a NumberFormat.
In particular, you need a DecimalFormat so you can call the setParseBigDecimal(true) method, since you want a BigDecimal as the result, otherwise it would likely have returned a Double.
DecimalFormat format = new DecimalFormat("¤#,##0.00", DecimalFormatSymbols.getInstance(Locale.US));
format.setParseBigDecimal(true);
BigDecimal number = (BigDecimal) format.parse(input);
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 am reading a currency from XML into Java.
String currency = "135.69";
When I convert this to BigDecimal I get:
System.out.println(new BigDecimal(135.69));
Output:
135.68999999999999772626324556767940521240234375.
Why is it that it outputs this many numbers? How can I avoid this? All I want is for it to output 135.69.
The BigDecimal(double) constructor can have unpredictable behaviors. It is preferable to use BigDecimal(String) or BigDecimal.valueOf(double).
System.out.println(new BigDecimal(135.69)); //135.68999999999999772626324556767940521240234375
System.out.println(new BigDecimal("135.69")); // 135.69
System.out.println(BigDecimal.valueOf(135.69)); // 135.69
The documentation for BigDecimal(double) explains in detail:
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.
The String constructor, on the other hand, is perfectly predictable: writing new BigDecimal("0.1") creates a BigDecimal which
is exactly equal to 0.1, as one would expect. Therefore, it is
generally recommended that the String constructor be used in
preference to this one.
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.
String currency = "135.69";
System.out.println(new BigDecimal(currency));
//will print 135.69
You are storing 135.69 as String in currency. But instead of passing variable currency, you are again passing 135.69(double value) into new BigDecimal().
So you are seeing a lot of numbers in the output.
If you pass the currency variable, your output will be 135.69
May I add something. If you are using currency you should use Scale(2), and you should probably figure out a round method.
BigDecimal b = BigDecimal.valueOf(d);
import java.math.*;
public class Test {
public static void main(String[] args)
{
// Creating a Double Object
Double d = new Double("785.254");
/// Assigning the bigdecimal value of ln to b
BigDecimal b = BigDecimal.valueOf(d);
// Displaying BigDecimal value
System.out.println("The Converted BigDecimal value is: " + b);
}
}
Spring Framework provides an excellent utils class for achieving this.
Util class : NumberUtils
String to BigDecimal conversion -
NumberUtils.parseNumber("135.00", BigDecimal.class);
Hi Guys you cant convert directly string to bigdecimal
you need to first convert it into long after that u will convert big decimal
String currency = "135.69";
Long rate1=Long.valueOf((currency ));
System.out.println(BigDecimal.valueOf(rate1));
I have a problem where my 999999999.9999999999 String is being rounded to 1,000,000,000 BigDecimal when I parse it.
Code:
NumberFormat format = new DecimalFormat("#.0000000000######");
format.setParseIntegerOnly(false);
Number number = format.parse(text);
Result:
number = 1.0E9
If I use the same format to parse the result BigDecimal back to String:
format.format(number) results in 1,000,000,000
Why does this happen and how I can force the original format.parse(text) call not to round?
Unless there's some code you've omitted, parse is returning a Double, not a BigDecimal. (Try System.out.println(number.getClass()) to check this.)
If you want a BigDecimal, you have to use setParseBigDecimal to tell it to return a BigDecimal. (And to do that, format has to be declared as DecimalFormat.)
DecimalFormat format = new DecimalFormat("#.0000000000######");
format.setParseBigDecimal(true);
Number number = format.parse(text);
I have a function called factorial which calculates factorial for a large number and returns in BidDecimal
BigDecimal temp_val1 = factorial(555);
the above gives 66140856092779467090983316712427699021235xxxxxxxxxxxxxxxxxxxxx
Now i have to format the BigDecimal value to string with scientific notation
NumberFormat sci_formate = new DecimalFormat("0.#####E0");
String temp_s1 = sci_formate.format(temp_val1);
the above gives 6.61409E1283
Now i need to convert the string temp_s1(6.61409E1283) back to BigDecimal which gives the value of temp_val1....???? How to do that....
try this
BigDecimal temp_val1 = new BigDecimal("6.61409E1283");
to format use
BigDecimal.toEngineeringString()
I have this code:
Long dval = new Long((new Date()).getTime());
System.out.println("ogval:"+dval);
Double dd = (double)dval;
System.out.println("dval:"+dd);
Here is the output:
ogval:1381490769636
dval:1.381490769636E12
When I convert the value to Double, it adds a decimal point. Can I do the typecasting and get the value in double as it is?
The desired output would be:
ogval:1381490769636
dval:1381490769636
I have a function whose argument accepts only double value. When I try to pass a timestamp, it passes the decimal value inside the method.
I can't edit the function because its an inbuilt function of some package.
Simple answer is no.
Floating types can contain integer up to some arbitrary value, given by the way floats are stored. If the number is too big, it gets converted to decimal.
If you need to work with big integer values use BigInteger class.
Great tool to examine those imperfections is this float converter.
Try 123456789 in the float converter, it won't be stored exactly.
Use DecimalFormat, like:
Long dval = new Long((new Date()).getTime());
System.out.println("ogval:" + dval);
Double dd = (double) dval;
DecimalFormat format=new DecimalFormat("##########");
System.out.println("dval:" + format.format(dd));
Your problem is not with the type that you are using, but with the format that you are applying to it. Currently, the default format is used, because string + double implicitly calls Double.toString, which converts your specific double to a String using scientific notation. You can force a different format if you wish by using printf or any other formatting method that Java makes available to you:
System.out.printf("dval: %12.0f", dd);
(demo)
as an alternative you can try using bigdecimal
Long dval = new Long((new Date()).getTime());
System.out.println("ogval:"+dval);
Double dd = (double)dval;
System.out.println("dval:"+dd);
BigDecimal bd = new BigDecimal(dval);
System.out.println("bdval:"+bd.toPlainString());