convert BigDecimal to Scientific Notation Java - java

How do i print this in scientific notation:
BigDecimal r= (a.subtract(exact, MathContext.DECIMAL128)).divide(exact, MathContext.DECIMAL128).stripTrailingZeros();
DecimalFormat format = new DecimalFormat("0.###E0");
System.out.println(new BigDecimal(format.format(r));
where:
a = 1.111111111111111160454356650006957352161407470703125
exact = 0.11
returns:
r = 0.900010000000000004
any ideas? I've also tried calling EngineeringString() on the BigDecimal but this also didn't seem to work for me

You overdid the thing. What you only need is:
System.out.println(format.format(r));
The DecimalFormat object does indeed create a string, creating a BigDecimal instance again would just parse the number from string again - and the toString() method is called on the BigDecimal instance, produing the output you described...
Some clarification
BigDecimal, and other numeric formats (and dates too!) are stored in binary formats in the memory, abstracted from how us, humans think of them. BigDecimal for example stores the decimal digits, and where the decimal point is. Floating point numbers are even more sophisticated. Date stores the seconds from The Epoch. You need to format them to be readable. Formatting means to create a String (or semantically similar) object, that represents the value of the given object in the desired format. This doesn't involve changing the original object in any way.
The default formatting, toString() provides one generic format. To get your output the way you'd like does not mean to change the value to be formatted right with toString(), but to transform the unchanged value into the right String. Nice example is Double.toString() (using sun.mic.FloatingDecimal): it does exponential notation when the number is large or small enough, but in between, it prints in plain decimal format...

Related

Converting String to BigDecimal with leading zeros

I am trying to convert an inputstream to objects and am having trouble with converting the below string to BigDecimal. I get 87.00 as the 0's are ignored. I am experimenting with DecimalFormat. Any help is appreciated. Thanks!
E.g. 0087 has to be converted to 00.87
You seem to indicate in comments that the initial string, "0087", is a fixed-point representation with two decimal places, there therefore being an implicit decimal point before the last two digits. There are several ways that you could convert that to a corresponding BigDecimal, but myself, I would go with this:
BigDecimal result = BigDecimal.valueOf(Long.parseLong("0087"), 2);
The key here is to understand that BigDecimals have two characteristic properties: an arbitrary-length sequence of decimal digits, and a scale conveying the place value of the least-significant digit, in the form of the number of digits to the right of the decimal point. The particular factory method demonstrated above accepts those as separate arguments, though it only works if the digit string is short enough to be represented as a long. The 2 corresponds directly to the number of (implicitly) fractional digits in your input.
Outputting the resulting BigDecimal as "00.87" instead of "0.87" is a separate issue, but doable, if it's really something you want.
Try this code
String str="0087";
int pos=str.lastIndexOf("0");
String resultat=str.substring(0,pos+1);
resultat+=".";
resultat+=str.substring(pos+1);
System.out.println(resultat);
new BigDecimal(resultat);

Is there any currency value that Jackson will serialize incorrectly?

Is is well known that numbers like 0.1 cannot be represented exactly in floating point. If you try to get a string representation of 0.1 though, you will see exactly "0.1" because Java(and many other languages) will do some implicit rounding for you when converting to a string. What's a bit more surprising is that when serializing 0.1 to a JSON you will still get the exact value even though it is serialized as a number and not a string type. I'm guessing this is because the entire JSON is basically a string and therefore Jackson just uses the normal string conversion on the double amount.
My question is as follows, is there any currency value(two decimal places or less) 0 < x < 500,000, for which converting from exact value to double, then to JSON or String, produces an incorrect value.
To give some context, I am currently writing something that will take some exact currency values, then pass said values directly to another service in JSON form without doing any calculations on them that may amplify the imprecision. I will probably use BigDecimal anyways to be safe, but I was wondering if it would be possible to get away with using double.
You should be fine: you can safely round-trip up to 15 significant figures from decimal to double and back to decimal, or in currency terms, up to $99 trillion to 1 cent accuracy.

Converting big decimal to double without exponential format

I'm doing calculations on High decimal precision BigDecimal objects.
I'm using a third party library that requires the parameter in double. When I try to convert this to double i get the values in exponential format instead of decimals .
BigDecimal 0.000035000000000
Double 3.5E-5
BigDecimal bd;
BigDecimal(0.0000349999999995631583260546904057264328002929687500);
bd= bd.setScale(15,BigDecimal.ROUND_CEILING);
Log.i("bd","bd "+bd.toPlainString());
Log.i("bd","double"+bd.doubleValue());
I have found various ways of converting this 3.5E-5 value as correct decimal in points but in String format only . Whereas I need the value in double
Able to get without exponential in String object But not in double
DecimalFormat df = new DecimalFormat("#");
df.setMaximumFractionDigits(16);
String test=df.format(bd,doubleValue());
System.out.println("op2 "+test);
Double test1=Double.parseDouble(test);
System.out.println("op2 "+test1);
OUTPUT op2 .000035 op2 3.5E-5
I'm struggling since since days to find a solution as I have no control over 3rd party library that requires the value to be in double
Refferred Links
Format BigDecimal without scientific notation with full precission
Converting exponential value in java to a number format
Conversion from exponential form to decimal in Java
How to resolve a Java Rounding Double issue
Java BigDecimal without E
How to Avoid Scientific Notation in Double?
My question is different then these links, I do not want the double as string without exponential instead I want it in double format only.
EDIT
If the double value passed is in exponential format, the NDK based libary will further do calculations on this object, which will result inmore decimal points and larger Exponential value. So, I want to pass a simple double without E
You seem to be confusing a double, a 64 bit value where different bits have a different meaning, with its string representation.
Let's take a value of 0.015625. Internally, the double is represented as 64 bits (I don't know right now which combination of bits, but that is irrelevant anyway).
But the string representation depends on the format settings of the library you are using. Note that the representations 0.015625 and 1.5625E-2 represent the exact same double value. The double is not stored as a string, it does not contain a . or an E, just a number of bits. The combination of these bits form its real value, and it is the same, no matter how you represent it as a string. If you have a different format setting, the result can just as well be 1.56E-2. This just means that the code that converts the internal bit combination of the double to a string does some rounding.
So, to obtain a double from a BigDecimal, simply use bd.doubleValue(). There is no need to use an intermediate string representation, and it can even be detrimental to do so, because if the string representation performs some rounding, you don't get the best approximation of the value in the BigDecimal.
So again, bd.doubleValue() is the only correct way to do this. This does not return a specific format, it simply returns the double that is closest to the value in the BigDecimal.
And again, do not confuse the double type with how it is represented as a string. These are different things. A double is a double is a double, and that is not stored as a string, exponential or plain or rounded or whatever.
Actually, BigDecimal.toString() and BigDecimal.toPlainString() also return different string representations of the same BigDecimal. AFAIK, there is even a third string conversion function, toEngineeringString(), which gives you yet another string representation of the same BigDecimal. This is similar for double: different output routines with different arguments return different strings for the exact same value.
use this: amount=value to be converted to double from string
double dd = new BigDecimal(amount).doubleValue();
String val = String.format("%.4f", dd);
BigDecimal bd = BigDecimal.valueOf(Double.valueOf(val));
Double d=bd.doubleValue() ;
DecimalFormat formatter = new DecimalFormat("0.0000");
System.out.println("doubleValue= " + formatter .format(d));

Java changing format of a double in an ArrayList<Double>

I have an ArrayList that i am inputting numbers into like
23466012.83
23466413.39
23466411.94
etc.
but when i reprint them from the array after i sort them they are reprinted like this
2.346601283E7
2.346641339E7
2.346641194E7
Why does java do this and how can this be fixed? (I want the format to be the same as when it was input)
Thanks!
Please review how Java handles primitive types and their related objects. By adding a "double" (lowercase) primitive type into a List, they are converted into "Double" objects, because List in Java can only hold objects, not primitives.
Therefore when you later output the Double object, it actually uses the simple toString() method of class Double to format the line. And this is implemented in a way to print the full range of Double in a readable format, this is why it chooses the so-called Scientific Notation with exponents display.
By using a more useful formatter, e.g. the Formatter class as mentioned in the comment or the MessageFormat class, you can better control how the output looks like.
Why does java do this
Java merely prints out your Double values using the default number format.
and how can this be fixed?
By explicitly specifying the desired number format.
I want the format to be the same as when it was input
First of all, you'll need to understand that you can't get "the same format as when it was input" because that information is irretrievably lost. It cannot be determined by inspecting a Double value how many significant digits were used to parse it.
If all you need is printing with two decimal places, one way to achieve it is with this statement:
System.out.format("%.2f%n", 23466012.83);
If, by any chance, you are not bound to using Double as the container of your numeric values, you may also consider BigDecimal, which can exactly represent an arbitrary value in decimal notation. It takes a lot more memory and is a lot slower in computation, but for many use cases neither of those may matter much. A larger issue is that the division of BigDecimal is an involved process because, by default, the API will insist on producing an exact result, which will fail for things as simple as 1/3.
System.out.format("%f%n", value);
Where value is the double primitive variable you want to print to sysout the screen.
Remove the %n if you want to continue printing on the same line.
There are existing answers that indicate how to format the output if you want the numbers output with two decimal places, regardless of how they were input.
If you really mean "I want the format to be the same as when it was input" there is only one practical option - store the input string. You can parse it as a double or BigDecimal for validation and when you need it as input to arithmetic, but always output it using the original.

Parsing a floating point number with mantissa in Java

Using the standard Java Double class to parse a floating point number with mantissa seems to omit the + sign from the exponent.
For example:
Double.parseDouble("1258124354E-28") returns 1.258124354E-19, but
Double.parseDouble("1243544322E+24") returns 1.243544322E33 (not E+33)
Is there any way to get the + sign using Double, without string post-processing?
The BigDecimal class does a better job, e.g.
new BigDecimal("1243544322E+24").toString() does return 1.243544322E+33
but it is generally slower than Double, which shows in intensive processing.
You need to differentiate between the value stored in a double and its string representation.
A double doesn't store a textual representation at all. 1.243544322E33 is 1.243544322E+33. They're the same value.
Now if you want to work on how you format a double value back to a String, that's a different matter - but the parsing you're doing is fine. You're not losing any information.
Jon is correct as above, its representing it correctly in memory. If you want it to display with the + on the mantissa then you are talking about string formatting the double.
Long winded official formatter reference
import java.util.Formatter;
double myDouble = Double.parseDouble("1243544322E+24");
Formatter formatter = new Formatter();
formatter.format("%+E", myDouble); //This should return with what you want, though with an extra + infront of the number
I haven't ran this code so I'm not 100% sure it will do the job. The + in the format specifier forces it to place a + or - sign for any number... I believe that extends to the mantissa.

Categories