I am converting a textView to Double then performing calculations then converting back to a string. I see that when my textview = "" it is throwing the error invalid Double "".
I added a check on the length of the text view prior to the calculation but it still is throwing the error. Any help is appreciated.
public void afterTextChanged(Editable s) {
if (textView.toString().length() > 0) {
Double ini = Double.parseDouble(textView.getText().toString());
Double calc = ini * 3.2808;
//passwordEditText.setText(textView.getText());
passwordEditText.setText(Double.toString(calc));
} else {
passwordEditText.setText("");
}
}
Use the getText method to get the text from a TextView. The toString method returns something else - a textual representation of the view itself. You can also trim it, in case there is extra whitespace.
String text = textView.getText().toString().trim();
if (text.length() > 0) {
Double ini = Double.parseDouble(text);
May be you are getting an empty string as a value, try changing if condition to the following:
if (textView.toString().trim().length() > 0) {
//logic
}
String text = textView.getText().trim();
if (!text.isEmpty()) {
try {
double ini = Double.parseDouble(text);
double calc = ini * 3.2808;
} catch (NumberFormatException e) {
---
double being the primitive type, Double an object wrapper, a bit more circumstantial converting ("unboxing") to double.
However parseDouble uses the computer language format: with a decimal point and no thousands separators. For another locale like most European countries the decimal separator is a comma. For portability:
NumberFormat nf = NumberFormat.getInstance(); // Default
NumberFormat nf = NumberFormat.getInstance(Locale.FRENCH); // Or fixed
try {
Number n = nf.parse(text);
double ini = n.doubleValue();
...
} catch (ParseException e) {
...
Even if parseDouble would suffice in your case, now thousand separators are possible. And for displaying numbers, a NumberFormat is even more useful.
Related
I primarily code in Python and I am completely new to java, so I am having difficulty with a simple programming task in Java regarding parsing through a .csv file. My .csv file has multiple columns and I want to parse through each line and store the second column as a string and the last column (column 4) as a double as a (string, double) pair. However, if column four does not contain a value that can be cast as a double value, I would like to assign a 0.0 as the double in the pair for that line. Each line from the .csv is passed to this function below, and I attempt to store the (string, double) pairs as mentioned, but after executing, all the pairs have 0.0 as the double value. I am not sure if there is there is a problem in my try/catch or looping method through each token. Any hints are appreciated.
public void a(Text t) {
StringTokenizer word = new StringTokenizer(t.toString(), ", ");
int count = 0;
double val = 0.0;
String keep = new String("");
boolean loop = true;
while (loop) {
String nextWord = word.nextToken ();
if (count == 2) {
//string in pair
keep = nextWord;
//loop until at last column and store word
while (word.hasMoreTokens()){
nextWord = word.nextToken();
}
loop = false;
//check if string can be cast to double
try{
Double.parseDouble(nextWord);
} catch(NumberFormatException e) {
val = 0.0;
} catch(NullPointerException e) {
val = 0.0;
}
val = Double.parseDouble(nextWord);
}
count++;
}
// then not relevant code to store (keep, val) pair for rest of code
}
You should avoid StringTokenizer because it is a deprecated library. Using string.split(). Here is a much simpler solution
public void a(Text t) {
String[] line = t.toString().split(", ");
//check if string can be cast to double
try{
Double.parseDouble(line[3]);
} catch(NumberFormatException e) {
line[3] = "0.0";
}
}
If the column 4 can be casted to double, it will keep it as it is otherwise it will put it as "0.0". The caveat is that since java can only have one datatype in string, you can't store it as double, however, whenever you want to use this value, you can parse it on spot without worrying that it will throw an exception".
I need to print a Double as a String but I don't know how many decimal places there will be and I have to be prepared for as many as possible. Right, now I'm using this ugly solution:
Double dubs = 0.000157;
NumberFormat formatter = new DecimalFormat(
"##.########################################################################################");
System.out.println(formatter.format(dubs));
You can do this with no conversion:
public class codesnippets {
public static void main(String[] args)
{
Double dubs = 0.000157;
System.out.printf("%f", dubs);
}
}
You can also use
Double dubs = 0.000157;
String dubs_format = String.format("%f", dubs);
System.out.println(dubs);
EDIT: Apparently there is a precision loss when using "%f" as a format string. If this is the case for you, use "%.10f"
Try here man. I think this is what you're saying. The answer given at the bottom.
Number of decimal digits in a double
Here is what I meant.
double d= 234.12413;
String text = Double.toString(Math.abs(d));
int integerPlaces = text.indexOf('.');
int decimalPlaces = text.length() - integerPlaces - 1;
Then you just concatenate them
String xmlString = integerPlaces.toString() + "." + decimalPlaces.toString();
This seemed to work based on Steampunkery's idea. The catch was that I needed an actual String which I realize I wasn't clear on.
String dubString= String.format("%f", dubs);
System.out.println(dubString);
i have four textboxes in my java application.
so i need to enter all value as double values.
my senario is like this
if i didnt enter any number to my textbox.
Double value should be zero.
if enter any values it should give the value i entered as double.
Converted all the string values into double values.
Double variables already initialized as 0.0
Double priceSec=0.0;
Double priceThird=0.0;
Double priceFourth=0.0;
Double priceFifth=0.0;
String priceTwo = cusPrice2.getText();
String priceThree = cusPrice3.getText();
String priceFour = cusPrice4.getText();
String priceFive = cusPrice5.getText();
priceSec = Double.parseDouble(priceTwo);
priceThird = Double.parseDouble(priceThree);
priceFourth = Double.parseDouble(priceFour);
priceFifth = Double.parseDouble(priceFive);
i initialized double values as 0.0 because if i didn't input any values into textboxes. default value will be zero.
but all these coding gives me an error like this:
Exception in thread "AWT-EventQueue-0" java.lang.NumberFormatException: empty String
at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1842)
at sun.misc.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
You can create a wrapper method for Double.parseDouble() and call it whenever you need.
priceSec = convertToDouble(priceTwo);
private static Double convertToDouble(String textValue) {
double doubleValue;
try {
doubleValue = Double.parseDouble(textValue);
} catch (Exception e) {
doubleValue = 0.0;
}
return doubleValue;
}
You can do it like this: You can use the try-catch clause to control the Exception
First create a method to convert the String to double
private double getValue(String textBoxData) {
try {
// parse the string value to double and return
return Double.parseDouble(textBoxData);
} catch (NumberFormatException e) {
// return zero if exception accrued due to wrong string data
return 0;
}
}
Now you can use as this:
// now you can get the double values as below:
priceSec = getValue(priceTwo);
priceThird = getValue(priceThree);
priceFourth = getValue(priceFour);
priceFifth = getValue(priceFive);
// Now you can do the work with your prices data
I am currently working on an Android project where we use string numbers with many digits in it.
So I want to know whether there is a way to convert the string numbers for e.g 1000000000 into comma separated string numbers for e.g(1,00,00,00,000) in Indian Locale format.
I got the US locale format string conversion but I want Indian locale format.
I would use format("% ,d", number) method of Format class, ensuring that I initialize the Formatter object with the appropriate locale (which I believe is en_IN for Indian).
Having said that, it would be easier for people to help you if you posted code on how you are doing it for US locale in the first place.
Ref : Formatting a Number Using a Custom Format
private String getFormatedData(String unformatedData) {
if(unformatedData != null) {
try {
//unformatedData.replaceAll(",", "");
Double result = Double.valueOf(unformatedData);
DecimalFormat myFormatter = new DecimalFormat("###,##0.00");
//DecimalFormat myFormatter = new DecimalFormat("#,###,###");
//If you don't want to show .00 format
return myFormatter.format(result);
} catch (NumberFormatException e) {
return unformatedData;
}
} else {
return "0.00";
}
}
Use this method.
I think you have to modify this method if you don't need .00 value. Let me work on it.
I think that you need to use NumberFormat so you can make a general case using current Locale settings of the user.
And I think that this is your current situation:
If you are formatting multiple numbers, it's more efficient to get the format and use it multiple times so that the system doesn't have to fetch the information about the local language and country conventions multiple times.
NumberFormat nf = NumberFormat.getInstance();
for (int i = 0; i < a.length; ++i) {
output.println(nf.format(myNumber[i]) + "; ");
}
The answer given by Pankaj Kumar gives the output in US format not in Indian Format.
If you want in US format it can be easily done by following code:
NumberFormat.getNumberInstance(Locale.US).format(35634646)
As shown here: Converting Integer to String with comma for thousands
To get the string with commas in Indian Format you can try this manual code
public String round(String d)
{
ArrayList<Integer> commas=new ArrayList<Integer>();
String output=null;
char[] preDecimal=d.split("[.]")[0].toCharArray();
int i=preDecimal.length-3;
System.out.println(i);
while(i>0)
{
commas.add(i);
i-=2;
}
StringBuilder sb=new StringBuilder();
for(i=0;i<preDecimal.length;i++)
{
sb.append(preDecimal[i]);
if(commas.contains(i+1))
sb.append(",");
}
output=sb.toString();
return output;
}
In Europe decimals are separated with ',' and we use optional '.' to separate thousands. I allow currency values with:
US-style 123,456.78 notation
European-style 123.456,78 notation
I use the next regular expression (from RegexBuddy library) to validate the input. I allow optional two-digits fractions and optional thousands separators.
^[+-]?[0-9]{1,3}(?:[0-9]*(?:[.,][0-9]{0,2})?|(?:,[0-9]{3})*(?:\.[0-9]{0,2})?|(?:\.[0-9]{3})*(?:,[0-9]{0,2})?)$
I would like to parse a currency string to a float. For example
123,456.78 should be stored as 123456.78
123.456,78 should be stored as 123456.78
123.45 should be stored as 123.45
1.234 should be stored as 1234
12.34 should be stored as 12.34
and so on...
Is there an easy way to do this in Java?
public float currencyToFloat(String currency) {
// transform and return as float
}
Use BigDecimal instead of Float
Thanks to everyone for the great answers. I have changed my code to use BigDecimal instead of float. I will keep previous part of this question with float to prevent people from doing the same mistakes I was gonna do.
Solution
The next code shows a function which transforms from US and EU currency to a string accepted by BigDecimal(String) constructor. That it is to say a string with no thousand separator and a point for fractions.
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class TestUSAndEUCurrency {
public static void main(String[] args) throws Exception {
test("123,456.78","123456.78");
test("123.456,78","123456.78");
test("123.45","123.45");
test("1.234","1234");
test("12","12");
test("12.1","12.1");
test("1.13","1.13");
test("1.1","1.1");
test("1,2","1.2");
test("1","1");
}
public static void test(String value, String expected_output) throws Exception {
String output = currencyToBigDecimalFormat(value);
if(!output.equals(expected_output)) {
System.out.println("ERROR expected: " + expected_output + " output " + output);
}
}
public static String currencyToBigDecimalFormat(String currency) throws Exception {
if(!doesMatch(currency,"^[+-]?[0-9]{1,3}(?:[0-9]*(?:[.,][0-9]{0,2})?|(?:,[0-9]{3})*(?:\\.[0-9]{0,2})?|(?:\\.[0-9]{3})*(?:,[0-9]{0,2})?)$"))
throw new Exception("Currency in wrong format " + currency);
// Replace all dots with commas
currency = currency.replaceAll("\\.", ",");
// If fractions exist, the separator must be a .
if(currency.length()>=3) {
char[] chars = currency.toCharArray();
if(chars[chars.length-2] == ',') {
chars[chars.length-2] = '.';
} else if(chars[chars.length-3] == ',') {
chars[chars.length-3] = '.';
}
currency = new String(chars);
}
// Remove all commas
return currency.replaceAll(",", "");
}
public static boolean doesMatch(String s, String pattern) {
try {
Pattern patt = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
Matcher matcher = patt.matcher(s);
return matcher.matches();
} catch (RuntimeException e) {
return false;
}
}
}
To answer a slightly different question: don't use the float type to represent currency values. It will bite you. Use a base-10 type instead, like BigDecimal, or an integer type like int or long (representing the quantum of your value - penny, for example, in US currency).
You will not be able to store an exact value - 123.45, say, as a float, and mathematical operations on that value (such as multiplication by a tax percentage) will produce rounding errors.
Example from that page:
float a = 8250325.12f;
float b = 4321456.31f;
float c = a + b;
System.out.println(NumberFormat.getCurrencyInstance().format(c));
// prints $12,571,782.00 (wrong)
BigDecimal a1 = new BigDecimal("8250325.12");
BigDecimal b1 = new BigDecimal("4321456.31");
BigDecimal c1 = a1.add(b1);
System.out.println(NumberFormat.getCurrencyInstance().format(c1));
// prints $12,571,781.43 (right)
You don't want to muck with errors when it comes to money.
With respect to the original question, I haven't touched Java in a little while, but I know that I'd like to stay away from regex to do this kind of work. I see this recommended; it may help you. Not tested; caveat developer.
try {
String string = NumberFormat.getCurrencyInstance(Locale.GERMANY)
.format(123.45);
Number number = NumberFormat.getCurrencyInstance(locale)
.parse("$123.45");
// 123.45
if (number instanceof Long) {
// Long value
} else {
// too large for long - may want to handle as error
}
} catch (ParseException e) {
// handle
}
Look for a locale with rules that match what you expect to see. If you can't find one, use multiple sequentially, or create your own custom NumberFormat.
I'd also consider forcing users to enter values in a single, canonical format. 123.45 and 123.456 look way too similar for my tastes, and by your rules would result in values that differ by a factor of 1000. This is how millions are lost.
As a generalized solution you can try
char[] chars = currency.toCharArray();
chars[currency.lastIndexOf(',')] = '.';
currency = new String(chars);
instead of
if(currency.length()>=3) {
char[] chars = currency.toCharArray();
if(chars[chars.length-2] == ',') {
chars[chars.length-2] = '.';
} else if(chars[chars.length-3] == ',') {
chars[chars.length-3] = '.';
}
currency = new String(chars);
}
so that fractional part can be of any length.
Try this.............
Locale slLocale = new Locale("de","DE");
NumberFormat nf5 = NumberFormat.getInstance(slLocale);
if(nf5 instanceof DecimalFormat) {
DecimalFormat df5 = (DecimalFormat)nf5;
try {
DecimalFormatSymbols decimalFormatSymbols = DecimalFormatSymbols.getInstance(slLocale);
decimalFormatSymbols.setGroupingSeparator('.');
decimalFormatSymbols.setDecimalSeparator(',');
df5.setDecimalFormatSymbols(decimalFormatSymbols);
df5.setParseBigDecimal(true);
ParsePosition pPosition = new ParsePosition(0);
BigDecimal n = (BigDecimal)df5.parseObject("3.321.234,56", pPosition);
System.out.println(n);
}catch(Exception exp) {
exp.printStackTrace();
}
}
A quick a dirty hack could be:
String input = input.replaceAll("\.,",""); // remove *any* , or .
long amount = Long.parseLong(input);
BigDecimal bd = BigDecimal.valueOf(amount).movePointLeft(2);
//then you could use:
bd.floatValue();
//but I would seriously recommended that you don't use floats for monetary amounts.
Note this will only work if the input is in the form ###.00, ie with exactly 2 decimal places. For example input == "10,022" will break this rather naive code.
Alternative is to use the BigDecimal(String) constructor, but you'll need to convert those euro style numbers to use '.' as the decimal separator, in addition to removing the thousand separators for both.