BigDecimal to string - java

I have a BigDecimal object and i want to convert it to string.
The problem is that my value got fraction and i get a huge number (in length) and i only need the original number in string for example:
for
BigDecimal bd = new BigDecimal(10.0001)
System.out.println(bd.toString());
System.out.println(bd.toPlainString());
the output is:
10.000099999999999766941982670687139034271240234375
10.000099999999999766941982670687139034271240234375
and i need the out put to be exactly the number 10.0001 in string

To get exactly 10.0001 you need to use the String constructor or valueOf (which constructs a BigDecimal based on the canonical representation of the double):
BigDecimal bd = new BigDecimal("10.0001");
System.out.println(bd.toString()); // prints 10.0001
//or alternatively
BigDecimal bd = BigDecimal.valueOf(10.0001);
System.out.println(bd.toString()); // prints 10.0001
The problem with new BigDecimal(10.0001) is that the argument is a double and it happens that doubles can't represent 10.0001 exactly. So 10.0001 is "transformed" to the closest possible double, which is 10.000099999999999766941982670687139034271240234375 and that's what your BigDecimal shows.
For that reason, it rarely makes sense to use the double constructor.
You can read more about it here, Moving decimal places over in a double

Your BigDecimal doesn't contain the number 10.0001, because you initialized it with a double, and the double didn't quite contain the number you thought it did. (This is the whole point of BigDecimal.)
If you use the string-based constructor instead:
BigDecimal bd = new BigDecimal("10.0001");
...then it will actually contain the number you expect.

For better support different locales use this way:
DecimalFormat df = new DecimalFormat();
df.setMaximumFractionDigits(2);
df.setMinimumFractionDigits(0);
df.setGroupingUsed(false);
df.format(bigDecimal);
also you can customize it:
DecimalFormat df = new DecimalFormat("###,###,###");
df.format(bigDecimal);

By using below method you can convert java.math.BigDecimal to String.
BigDecimal bigDecimal = new BigDecimal("10.0001");
String bigDecimalString = String.valueOf(bigDecimal.doubleValue());
System.out.println("bigDecimal value in String: "+bigDecimalString);
Output:
bigDecimal value in String: 10.0001

// Convert BigDecimal number To String by using below method //
public static String RemoveTrailingZeros(BigDecimal tempDecimal)
{
tempDecimal = tempDecimal.stripTrailingZeros();
String tempString = tempDecimal.toPlainString();
return tempString;
}
// Recall RemoveTrailingZeros
BigDecimal output = new BigDecimal(0);
String str = RemoveTrailingZeros(output);

If you just need to set precision quantity and round the value, the right way to do this is use it's own object for this.
BigDecimal value = new BigDecimal("10.0001");
value = value.setScale(4, RoundingMode.HALF_UP);
System.out.println(value); //the return should be "10.0001"
One of the pillars of Oriented Object Programming (OOP) is "encapsulation", this pillar also says that an object should deal with it's own operations, like in this way:

The BigDecimal can not be a double.
you can use Int number.
if you want to display exactly own number, you can use the String constructor of BigDecimal .
like this:
BigDecimal bd1 = new BigDecimal("10.0001");
now, you can display bd1 as 10.0001
So simple.
GOOD LUCK.

To archive the necessary result with double constructor you need to round the BigDecimal before convert it to String e.g.
new java.math.BigDecimal(10.0001).round(new java.math.MathContext(6, java.math.RoundingMode.HALF_UP)).toString()
will print the "10.0001"

Related

How to preserve precision of Bigdecimal in Java?

I am using xs:decimal as Type in XSD with length as
value="9999999999999999.999999999999999"
BigDecimal big = new BigDecimal("0.000000000001");
System.out.println(big); // Actual 1e-12 Expected 0.000000000001
i cannot use toPlainString(), since i want it in BigDecimal
From the javadoc : BigDecimal.toPlainString
public String toPlainString()
Returns a string representation of this BigDecimal without an exponent field.
BigDecimal bd = new BigDecimal("0.000000001");
System.out.println(bd);
System.out.println(bd.toPlainString());
Will output :
1E-9
0.000000001

Bigdecimal Not giving exact output in Java

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)))));

Remove Decimals from String

I have a function that converst a BigDecimal into a String plus the currency. When I use this the number (e.g. 34) turns into a number with a lot of decimals (e.g. 34.000000).
What can I do to solve this and just show the 34?
Here is my function:
row.put("Money", GcomNullPointerValidator.isNullField(formatUtils.formatCurrency(MoneyDto.getAmount().stripTrailingZeros())));
What is the language? Java?
You can use the split() function of String if you just want to keep numbers before "." :
String mystring = "34.000000";
String correctstring[] = mystring.split(".");
System.out.println(correctstring[0]);
// display : 34
it will delete all digits after "." !
Inside your method that converts a BigDecimal into a String, you can use BigDecimal.setScale() to set the number of digits after the decimal point. For example:
BigDecimal d = new BigDecimal("34.000000");
BigDecimal d1 = d.setScale(2, BigDecimal.ROUND_HALF_UP); // yields 34.00
BigDecimal d2 = d.setScale(0, BigDecimal.ROUND_HALF_UP); // yields 34
You can use this:
String number = "150.000";
number.replaceAll("\\.\\d+$", "");
Or you can use this:
number.split(Pattern.quote("."))[0];

Truncate the fractional part of a BigDecimal when its scale is zero in Java

I need to remove the fractional part of a BigDecimal value when its scale has a value of zero. For example,
BigDecimal value = new BigDecimal("12.00").setScale(2, RoundingMode.HALF_UP);
It would assign 12.00. I want it to assign only 12 to value in such cases.
BigDecimal value = new BigDecimal("12.000000").setScale(2, RoundingMode.HALF_UP);
should assign 12,
BigDecimal value = new BigDecimal("12.0001").setScale(2, RoundingMode.HALF_UP);
should assign 12.
BigDecimal value = new BigDecimal("12.0051").setScale(2, RoundingMode.HALF_UP);
should assign12.01
BigDecimal value = new BigDecimal("00.000").setScale(2, RoundingMode.HALF_UP);
should assign 0.
BigDecimal value = new BigDecimal("12.3456").setScale(2, RoundingMode.HALF_UP);
should assign 12.35 and alike. Is this possible? What is the best way to do?
For the crosslink from there: https://codereview.stackexchange.com/questions/24299/is-this-the-way-of-truncating-the-fractional-part-of-a-bigdecimal-when-its-scale
Is this possible? What is the best way to do?
Probably stripTrailingZeros().
To check your tests:
public static void main(final String[] args) {
check(truncate("12.000000"), "12");
check(truncate("12.0001"), "12");
check(truncate("12.0051"), "12.01");
check(truncate("12.99"), "12.99");
check(truncate("12.999"), "13");
check(truncate("12.3456"), "12.35");
System.out.println("if we see this message without exceptions, everything is ok");
}
private static BigDecimal truncate(final String text) {
BigDecimal bigDecimal = new BigDecimal(text);
if (bigDecimal.scale() > 2)
bigDecimal = new BigDecimal(text).setScale(2, RoundingMode.HALF_UP);
return bigDecimal.stripTrailingZeros();
}
private static void check(final BigDecimal bigDecimal, final String string) {
if (!bigDecimal.toString().equals(string))
throw new IllegalStateException("not equal: " + bigDecimal + " and " + string);
}
output:
if we see this message without exceptions, everything is ok
The following code does what you specify with the help of regex and the construction of BigDecimal, it is probably not the most efficient way to go about:
BigDecimal value = new BigDecimal("12.0000").setScale(2, RoundingMode.HALF_UP);
Pattern pattern = Pattern.compile("\\d+\\.(\\d)0");
Matcher matcher = pattern.matcher(value.toString());
if (matcher.find()) {
if (matcher.group(1).equals("0"))
value = value.setScale(0);
else
value = value.setScale(1);
}
Note: this also makes 12.100 -> 12.1, I assume that is wanted functionality.
Instead of modifying the original value on my own by hand, I have simply tried to apply some conditions like,
String text="123.008";
BigDecimal bigDecimal=new BigDecimal(text);
if(bigDecimal.scale()>2)
{
bigDecimal=new BigDecimal(text).setScale(2, RoundingMode.HALF_UP);
}
if(bigDecimal.remainder(BigDecimal.ONE).compareTo(BigDecimal.ZERO)==0)
{
bigDecimal=new BigDecimal(text).setScale(0, BigDecimal.ROUND_HALF_UP);
}
System.out.println("bigDecimal = "+bigDecimal);
The first if condition checks, if the scale is greater than 2. If so, then perform the rounding operation as specified.
The next if condition checks, if the value of the fractional part yields zero. If so, then truncate it. Two BigDecimal objects that are equal in value but have a different scale (like 2.0 and 2.00) are considered equal by the compareTo() method. Therefore, the condition is satisfied whenever the the value of the fractional part is evaluated to zero.
Otherwise, the original value is left untouched (if the scale is either 1 or 2).
If I'm missing something or it's a wrong thing to implement, then please clarify it.
Try this one:
new BigDecimal("12.3456").setScale(2, RoundingMode.FLOOR).stripTrailingZeros()

Avoid round number when casting a float to string

I need avoid round number when casting a float to string, I need the number is exactly the same.
In this moment if I make this:
String value = String.valueOf(1234567.99);
The the value = 1234568.0 ,so I need the value = 1234567.99 after casting.
1234567.99 can't be exactly represented as a float. The nearest float is actually equal to 1234568.
If you want more precision, you can use a double: 1234567.99d will do what you expect.
You can run this simple test to check it (it is in Java but easily transposable on android by replacing the println):
public static void main(String[] args) {
float f = 1234567.99f;
double d = 1234567.99d;
System.out.println(new BigDecimal(f));
System.out.println(new BigDecimal(d));
}
prints:
1234568
1234567.98999999999068677425384521484375
Note: String.valueOf(double) does round the double to another representation, with less decimals, of the same double. In other words, as you see above 1234567.99d can't be represented as a double and the nearest double is 1234567.98999999999068677425384521484375. But String.valueOf figures it out and uses the first representation of that double (with only 2 decimals) since they are effectively the same double according to the specifications of the language.
String.valueOf() never round off any number you have some other issue but you can try it as:
String value = ""+1234567.99;
String s = Double.toString(1234567.99);
update: for more control over the string's format, use DecimalFormat and DecimalFormatSymbols
For example:
java.text.DecimalFormat formater = new java.text.DecimalFormat();
formater.setMinimumFractionDigits(0);
formater.setMaximumFractionDigits(3);
formater.setGroupingUsed(false);
java.text.DecimalFormatSymbols dfs = new java.text.DecimalFormatSymbols();
dfs.setNaN("NaN");
formater.setDecimalFormatSymbols(dfs);
String s = formater.format(1234567.99);

Categories