Convert String characters in Scientific Notation format into Standard Notation - java

I have a user string generated by some computations. The user string is "3.2E7"
It is written in Scientific Notation. I need to convert it to standard notation because
the drawing instructions on the App overlap if it reads a Scientific Notation number.
I do know how to convert it to Standard Notation use the Number class, as the following shows:
String generated = "3.2E7"
try{
NumberFormat format = NumberFormat.getInstance();
Number my_number = format.parse(generated);
System.out.println("see my number: " + my_number); //this prints correctly: 32000000
}catch(Exception exception){
Log.d("see009",""+exception);
}
Now, the problem I am having is that if the variable 'generated' < 1 but greater than zero. Then, the NumberFormat class does not convert it properly:
String generated = "3.2E-7";
//inside the try catch block from above:
System.out.println("see my number: " + my_number); //this prints 3.2E-7 NOT: 0.00000032
Doesn't the Number class accept non-integers. How can I make the NumberFormat object format the Scientific notation number less than 1?

Working with the BigDecimal class I have been able to overcome the problem:
Simply do this:
String generated = "3.2E7";
BigDecimal big_decimal = new BigDecimal(generated);
System.out.println("look at this: " + big_decimal.toPlainString()); //will print: 32000000
generated = "3.2E-7";
big_decimal = new BigDecimal(generated);
System.out.println("look at this: " + big_decimal.toPlainString()); //will print: 0.00000032
BigDecimal even worked with powers in the magnitude of 20. It is a very efficient solution that is good for my needs.

Related

Is Java assigning incorrect value to double variable? [duplicate]

I want to print a double value in Java without exponential form.
double dexp = 12345678;
System.out.println("dexp: "+dexp);
It shows this E notation: 1.2345678E7.
I want it to print it like this: 12345678
What is the best way to prevent this?
Java prevent E notation in a double:
Five different ways to convert a double to a normal number:
import java.math.BigDecimal;
import java.text.DecimalFormat;
public class Runner {
public static void main(String[] args) {
double myvalue = 0.00000021d;
//Option 1 Print bare double.
System.out.println(myvalue);
//Option2, use decimalFormat.
DecimalFormat df = new DecimalFormat("#");
df.setMaximumFractionDigits(8);
System.out.println(df.format(myvalue));
//Option 3, use printf.
System.out.printf("%.9f", myvalue);
System.out.println();
//Option 4, convert toBigDecimal and ask for toPlainString().
System.out.print(new BigDecimal(myvalue).toPlainString());
System.out.println();
//Option 5, String.format
System.out.println(String.format("%.12f", myvalue));
}
}
This program prints:
2.1E-7
.00000021
0.000000210
0.000000210000000000000001085015324114868562332958390470594167709350585
0.000000210000
Which are all the same value.
Protip: If you are confused as to why those random digits appear beyond a certain threshold in the double value, this video explains: computerphile why does 0.1+0.2 equal 0.30000000000001?
http://youtube.com/watch?v=PZRI1IfStY0
You could use printf() with %f:
double dexp = 12345678;
System.out.printf("dexp: %f\n", dexp);
This will print dexp: 12345678.000000. If you don't want the fractional part, use
System.out.printf("dexp: %.0f\n", dexp);
0 in %.0f means 0 places in fractional part i.e no fractional part. If you want to print fractional part with desired number of decimal places then instead of 0 just provide the number like this %.8f. By default fractional part is printed up to 6 decimal places.
This uses the format specifier language explained in the documentation.
The default toString() format used in your original code is spelled out here.
In short:
If you want to get rid of trailing zeros and Locale problems, then you should use:
double myValue = 0.00000021d;
DecimalFormat df = new DecimalFormat("0", DecimalFormatSymbols.getInstance(Locale.ENGLISH));
df.setMaximumFractionDigits(340); // 340 = DecimalFormat.DOUBLE_FRACTION_DIGITS
System.out.println(df.format(myValue)); // Output: 0.00000021
Explanation:
Why other answers did not suit me:
Double.toString() or System.out.println or FloatingDecimal.toJavaFormatString uses scientific notations if double is less than 10^-3 or greater than or equal to 10^7
By using %f, the default decimal precision is 6, otherwise you can hardcode it, but it results in extra zeros added if you have fewer decimals. Example:
double myValue = 0.00000021d;
String.format("%.12f", myvalue); // Output: 0.000000210000
By using setMaximumFractionDigits(0); or %.0f you remove any decimal precision, which is fine for integers/longs, but not for double:
double myValue = 0.00000021d;
System.out.println(String.format("%.0f", myvalue)); // Output: 0
DecimalFormat df = new DecimalFormat("0");
System.out.println(df.format(myValue)); // Output: 0
By using DecimalFormat, you are local dependent. In French locale, the decimal separator is a comma, not a point:
double myValue = 0.00000021d;
DecimalFormat df = new DecimalFormat("0");
df.setMaximumFractionDigits(340);
System.out.println(df.format(myvalue)); // Output: 0,00000021
Using the ENGLISH locale makes sure you get a point for decimal separator, wherever your program will run.
Why using 340 then for setMaximumFractionDigits?
Two reasons:
setMaximumFractionDigits accepts an integer, but its implementation has a maximum digits allowed of DecimalFormat.DOUBLE_FRACTION_DIGITS which equals 340
Double.MIN_VALUE = 4.9E-324 so with 340 digits you are sure not to round your double and lose precision.
You can try it with DecimalFormat. With this class you are very flexible in parsing your numbers.
You can exactly set the pattern you want to use.
In your case for example:
double test = 12345678;
DecimalFormat df = new DecimalFormat("#");
df.setMaximumFractionDigits(0);
System.out.println(df.format(test)); //12345678
I've got another solution involving BigDecimal's toPlainString(), but this time using the String-constructor, which is recommended in the javadoc:
this constructor is compatible with the values returned by Float.toString and Double.toString. This is generally the preferred way to convert a float or double into a BigDecimal, as it doesn't suffer from the unpredictability of the BigDecimal(double) constructor.
It looks like this in its shortest form:
return new BigDecimal(myDouble.toString()).stripTrailingZeros().toPlainString();
NaN and infinite values have to be checked extra, so looks like this in its complete form:
public static String doubleToString(Double d) {
if (d == null)
return null;
if (d.isNaN() || d.isInfinite())
return d.toString();
return new BigDecimal(d.toString()).stripTrailingZeros().toPlainString();
}
This can also be copied/pasted to work nicely with Float.
For Java 7 and below, this results in "0.0" for any zero-valued Doubles, so you would need to add:
if (d.doubleValue() == 0)
return "0";
Java/Kotlin compiler converts any value greater than 9999999 (greater than or equal to 10 million) to scientific notation ie. Epsilion notation.
Ex: 12345678 is converted to 1.2345678E7
Use this code to avoid automatic conversion to scientific notation:
fun setTotalSalesValue(String total) {
var valueWithoutEpsilon = total.toBigDecimal()
/* Set the converted value to your android text view using setText() function */
salesTextView.setText( valueWithoutEpsilon.toPlainString() )
}
This will work as long as your number is a whole number:
double dnexp = 12345678;
System.out.println("dexp: " + (long)dexp);
If the double variable has precision after the decimal point it will truncate it.
I needed to convert some double to currency values and found that most of the solutions were OK, but not for me.
The DecimalFormat was eventually the way for me, so here is what I've done:
public String foo(double value) //Got here 6.743240136E7 or something..
{
DecimalFormat formatter;
if(value - (int)value > 0.0)
formatter = new DecimalFormat("0.00"); // Here you can also deal with rounding if you wish..
else
formatter = new DecimalFormat("0");
return formatter.format(value);
}
As you can see, if the number is natural I get - say - 20000000 instead of 2E7 (etc.) - without any decimal point.
And if it's decimal, I get only two decimal digits.
I think everyone had the right idea, but all answers were not straightforward.
I can see this being a very useful piece of code. Here is a snippet of what will work:
System.out.println(String.format("%.8f", EnterYourDoubleVariableHere));
the ".8" is where you set the number of decimal places you would like to show.
I am using Eclipse and it worked no problem.
Hope this was helpful. I would appreciate any feedback!
The following code detects if the provided number is presented in scientific notation. If so it is represented in normal presentation with a maximum of '25' digits.
static String convertFromScientificNotation(double number) {
// Check if in scientific notation
if (String.valueOf(number).toLowerCase().contains("e")) {
System.out.println("The scientific notation number'"
+ number
+ "' detected, it will be converted to normal representation with 25 maximum fraction digits.");
NumberFormat formatter = new DecimalFormat();
formatter.setMaximumFractionDigits(25);
return formatter.format(number);
} else
return String.valueOf(number);
}
This may be a tangent.... but if you need to put a numerical value as an integer (that is too big to be an integer) into a serializer (JSON, etc.) then you probably want "BigInterger"
Example:
value is a string - 7515904334
We need to represent it as a numerical in a Json message:
{
"contact_phone":"800220-3333",
"servicer_id":7515904334,
"servicer_name":"SOME CORPORATION"
}
We can't print it or we'll get this:
{
"contact_phone":"800220-3333",
"servicer_id":"7515904334",
"servicer_name":"SOME CORPORATION"
}
Adding the value to the node like this produces the desired outcome:
BigInteger.valueOf(Long.parseLong(value, 10))
I'm not sure this is really on-topic, but since this question was my top hit when I searched for my solution, I thought I would share here for the benefit of others, lie me, who search poorly. :D
use String.format ("%.0f", number)
%.0f for zero decimal
String numSring = String.format ("%.0f", firstNumber);
System.out.println(numString);
I had this same problem in my production code when I was using it as a string input to a math.Eval() function which takes a string like "x + 20 / 50"
I looked at hundreds of articles... In the end I went with this because of the speed. And because the Eval function was going to convert it back into its own number format eventually and math.Eval() didn't support the trailing E-07 that other methods returned, and anything over 5 dp was too much detail for my application anyway.
This is now used in production code for an application that has 1,000+ users...
double value = 0.0002111d;
String s = Double.toString(((int)(value * 100000.0d))/100000.0d); // Round to 5 dp
s display as: 0.00021
This will work not only for a whole numbers:
double dexp = 12345678.12345678;
BigDecimal bigDecimal = new BigDecimal(Double.toString(dexp));
System.out.println("dexp: "+ bigDecimal.toPlainString());
My solution:
String str = String.format ("%.0f", yourDouble);
For integer values represented by a double, you can use this code, which is much faster than the other solutions.
public static String doubleToString(final double d) {
// check for integer, also see https://stackoverflow.com/a/9898613/868941 and
// https://github.com/google/guava/blob/master/guava/src/com/google/common/math/DoubleMath.java
if (isMathematicalInteger(d)) {
return Long.toString((long)d);
} else {
// or use any of the solutions provided by others, this is the best
DecimalFormat df =
new DecimalFormat("0", DecimalFormatSymbols.getInstance(Locale.ENGLISH));
df.setMaximumFractionDigits(340); // 340 = DecimalFormat.DOUBLE_FRACTION_DIGITS
return df.format(d);
}
}
// Java 8+
public static boolean isMathematicalInteger(final double d) {
return StrictMath.rint(d) == d && Double.isFinite(d);
}
This works for me. The output will be a String.
String.format("%.12f", myvalue);
Good way to convert scientific e notation
String.valueOf(YourDoubleValue.longValue())

how to display a string with two decimal places which is carrying currency value in dollar

I'm taking a value from the mobile application which I'm getting in string format something like "$000"(which actually $0.00 ) similarly I want to convert all the value into two decimal place say if I get "$279"(which is in application actually $2.79)
I don't know the correct approach because further in I have compair this value to some other string.
so I want to keep this as String but at the same time I want to put decimal after two place always whatever the number.
I tried to Decimal formatter for money but gave me "object as a number format" exception
sends
String accLastFourDigits, getCurrAmt, currAmt;
getCurrAmt = getDriver().findElement(by("overview.current_balance")).getText();
DecimalFormat money = new DecimalFormat("$0.00");
currAmt = money.format(getCurrAmt);
You could use builtin NumberFormat provided by JAVA to parse different country Currencies as shown below. Also I am dividing the resulting number by 100, so as to satisfy the requirement, that $978 is read as 9.78.
NumberFormat usFormat = NumberFormat.getCurrencyInstance(Locale.US);
String currencyValue = "$100";
try {
System.out.println(usFormat.parse(currencyValue).intValue()/100);
}catch(ParseException e) {
e.printStackTrace();
}
Here, I am setting the currency to US and then parsing a string with dollar sign.
You could also use the format method of NumberFormat to print the currency value in respective currency formats, as shown below
NumberFormat usFormat = NumberFormat.getCurrencyInstance(Locale.US);
String currencyValue = "$100";
try {
Number value = usFormat.parse(currencyValue).intValue()/100;
System.out.println("Number value : " + value);
System.out.printf("In Currency : "+usFormat.format(value));
}catch(ParseException e) {
e.printStackTrace();
}
You have this exception because format method expect number type argument. What you need to do then is to remove all non digits characters from the input string
getCurrAmt = getCurrAmt.replaceAll("[^\\d.]", ""); // please note that replaceAll method has poor performance
and parse it to Integer when calling format method
money.format(Integer.parseInt(getCurrAmt))
As pointed out replaceAll method is not very efficient because it needs to compile Pattern every single time and it's better to use Matcher - you can read about this in this topic:
String replaceAll() vs. Matcher replaceAll() (Performance differences)
How about this?
String inputStr = "$279";
NumberFormat usCurrency = NumberFormat.getCurrencyInstance(Locale.US);
usCurrency.setParseIntegerOnly(true);
long num = (Long)usCurrency.parse(inputStr);
BigDecimal amount = new BigDecimal(num);
amount = amount.scaleByPowerOfTen(-2);
log.info("amount: {}", usCurrency.format(amount));

Number format exception for decimal number when given double

When I run the following script to check inputQty greater than AvailQty I am getting the following:
java.lang.NumberFormatException: For input string: "97,045.1193"
This error occurs if availableQty is a decimal number. The value is delivered from a database, can you please correct where I am wrong?
double AvailQty = Double.valueOf(AQTY.getValue());
double inputQty = Double.valueOf(QTY.getValue());
if(inputQty > AvailQty){
session.setStatusMessage("Not Enough Quantity");
//Abort operation
throw new AbortHandlerException();
}
Thanks
Your string contains commas, remove any commas before parsing.
Double.valueOf(INV.AVAILQTY.getValue().replaceAll(",", ""));
It can't format it because it doesn't accept the comma. You could do something like Double.valueOf(INV.AVAILQTY.getValue().replaceAll(",", "")) and Double.valueOf(XX_IGL_QTY.getValue().replaceAll(",", "")) to remove any commas before parsing.
Simple, your string contains commas. This is not legal. All you can have are numbers and a dot (decimal separator).
I don't know where you get the value from, but if it's not something you can change on that side, you will have to do some hacking ;)
Double.valueOf(INV.AVAILQTY.getValue().replaceAll(",","");
Rather than re-formatting the string to do the conversion, you can tell the formatter to read the numbers using whatever format you like.
This answer shows how to change the formatting.
Here's a sample test to show how the same number in your question can be parsed successfully:
#Test
public void showNumberFormats() throws ParseException {
String rawAvailQty = "97,045.1193";
String rawInptQty = "98,045.3421";
NumberFormat nf = NumberFormat.getNumberInstance();
double AvailQty = nf.parse(rawAvailQty).doubleValue();
double inputQty = nf.parse(rawInptQty).doubleValue();
if(inputQty > AvailQty){
//Abort operation
System.err.println("Could not perform operation");
}
System.out.println("Available qty: " + AvailQty);
System.out.println("Input qty: " + inputQty);
}
Prints:
Could not perform operation
Available qty: 97045.1193
Input qty: 98045.3421

Java Big Decimal problem

I am using java big decimal as follwing:
class test bigDecimal{
private BigDecimal decimalResult;
public boolean iterate(String value) {
if (value == null) {
return true;
}
System.out.println("value is: " + value);
BigDecimal temp = new BigDecimal(value);
System.out.println("temp val is: " + temp);
if (decimalResult == null) {
decimalResult = temp;
} else {
decimalResult = decimalResult.add(temp);
}
return true;
}
}
all the strings that I am using to create big Decimal have scale of 6. For eg: 123456.678000, 456789.567890
But If I give a big list of strings as input and check the sum, I get output with 8 digits after decimal point. for eg. something like: 2939166.38847228.
I wonder why does BigDecimal change this scale ? all my input has scale of 6.
Any inputs are appreciated.
-thanks
Please read the javadoc for BigDecimal:
http://download.oracle.com/javase/6/docs/api/java/math/BigDecimal.html
Internally all BigDecimals get converted to a some internal format.
If you want to get a specific format you have to call it appropriate.
You could use scaleByPowerOfTen(int n) with n=6 for example
Oh, and by the way never use new BigDecimal, use BigDecimal.valueOf instead.
EDIT:
NumberFormat numberFormat = NumberFormat.getInstance(); // use a locale here
String formated = df.format(myUnformatedBigDecimal);
It is not a problem of internal representation. This way the BigDecimal.toString() works. It calls layoutChars(true) - the private method that formats number. It has hard coded scale of 6. But I think it does not matter. You do not really have to pint all digits. BigDecimal provides ability to calculate high precision numbers. That's what it does.
Big decimal is giving an exact output, but that output is more accurate than 6 digits, so the best way to get 6 digit output is removing the last 2 decimals by converting the BigDecimal into string and doing something like that:
String myOutput = new
BigDecimal("1000.12345678").toString();
myOutput = myOutput.substring(myOutput.length-2,
myOutput.length);

Conversion from exponential form to decimal in Java

I want to convert exponential to decimal. e.g. 1.234E3 to 1234.
It is not really a conversion, but about how you display the number. You can use NumberFormat to specify how the number should be displayed.
Check the difference:
double number = 100550000.75;
NumberFormat formatter = new DecimalFormat("#0.00");
System.out.println(number);
System.out.println(formatter.format(number));
How about BigDecimal.valueOf(doubleToFormat).toPlainString()
While working with Doubles and Long numbers in Java you will see that most of the value are displayed in Exponential form.
For Example: In following we are multiplying 2.35 with 10000 and the result is printed.
//Division example
Double a = 2.85d / 10000;
System.out.println("1. " + a.doubleValue());
//Multiplication example
a = 2.85d * 100000000;
System.out.println("2. " + a.doubleValue());
Result:
2.85E-4
2.85E8
Thus you can see the result is printed in exponential format. Now you may want to display the result in pure decimal format like: 0.000285 or 285000000. You can do this simply by using class java.math.BigDecimal. In following example we are using BigDecimal.valueOf() to convert the Double value to BigDecimal and than .toPlainString() to convert it into plain decimal string.
import java.math.BigDecimal;
//..
//..
//Division example
Double a = 2.85d / 10000;
System.out.println("1. " + BigDecimal.valueOf(a).toPlainString());
//Multiplication example
a = 2.85d * 100000000;
System.out.println("2. " + BigDecimal.valueOf(a).toPlainString());
Result:
0.000285
285000000
The only disadvantage of the above method is that it generates long strings of number. You may want to restrict the value and round off the number to 5 or 6 decimal point. For this you can use java.text.DecimalFormat class. In following example we are rounding off the number to 4 decimal point and printing the output.
import java.text.DecimalFormat;
//..
//..
Double a = 2.85d / 10000;
DecimalFormat formatter = new DecimalFormat("0.0000");
System.out.println(formatter .format(a));
Result:
0.0003
I have just tried to compress this code with one line, it will print value of 'a' with two decimal places:
new DecimalFormat("0.00").format(BigDecimal.valueOf(a).toPlainString());
Happy Converting :)
you can turn it into a String using
DecimalFormat
the answer by #b.roth is correct only if it is country specific. I used that method and got i18n issue , because the new DecimalFormat("#0.00) takes the decimal seperator of the particular country. For ex if a country uses decimal seperation as "," , then the formatted value will be in 0,00 ( ex.. 1.2e2 will be 120.00 in some places and 120,00 ) in some places due to i18n issue as said here..
the method that i prefer is `(new BigDecimal("1.2e2").toPlainString() )
just add following tag to jspx:-
<f:convertNumber maxFractionDigits="4" minFractionDigits="2" groupingUsed="false"/>
String data = Long.toString((long) 3.42E8);
System.out.println("**************"+data);
try the following
long l;
double d; //It holds the double value.such as 1.234E3
l=Double.valueOf(time_d).longValue();
you get the decimal value in the variable l.
You can do:
BigDecimal
.valueOf(value)
.setScale(decimalLimit, RoundingMode.HALF_UP)
.toPlainString()

Categories