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;
}
Related
While working on currency I need to change a value of a JTextBox(say txtRetilPrice) in the format of Rs.1,500.00. Now for manipulation, I need to change the value of txtRetailPrice to 1500. I tried this code but couldn't succeed.
if (!(txtRetailPrice.getText().equals(""))) {
txtRetailPrice.setText(txtRetailPrice.getText().replaceAll("Rs", ""));
txtRetailPrice.setText(txtRetailPrice.getText().replaceAll(".", ""));
txtRetailPrice.setText(txtRetailPrice.getText().replaceAll(",", ""));
}
Actually, on the got focus of the JTextBox, I want to show as 1500 and on the lost focus, it will change to Rs.1,500.00. The lost focus' work is done but for this I need help.
You can use the NumberFormat class to get this done using India as the country and English as the language for Locale. Here is a simple example for both parsing and formatting.
static void IndiaCurrencyFormat() throws ParseException {
NumberFormat numberFormat = NumberFormat.getCurrencyInstance(new Locale("en", "in"));
int number = 15000;
System.out.println(numberFormat.format(number));
String currency = "Rs.15,000.00";
System.out.println(numberFormat.parse(currency));
}
I want to convert some numbers which I got as strings into Doubles, but these numbers are not in US standard locale, but in a different one. How can I do that?
Try java.text.NumberFormat. From the Javadocs:
To format a number for a different Locale, specify it in the call to getInstance.
NumberFormat nf = NumberFormat.getInstance(Locale.FRENCH);
You can also use a NumberFormat to parse numbers:
myNumber = nf.parse(myString);
parse() returns a Number; so to get a double, you must call myNumber.doubleValue():
double myNumber = nf.parse(myString).doubleValue();
Note that parse() will never return null, so this cannot cause a NullPointerException. Instead, parse throws a checked ParseException if it fails.
Edit: I originally said that there was another way to convert to double: cast the result to Double and use unboxing. I thought that since a general-purpose instance of NumberFormat was being used (per the Javadocs for getInstance), it would always return a Double. But DJClayworth points out that the Javadocs for parse(String, ParsePosition) (which is called by parse(String)) say that a Long is returned if possible. Therefore, casting the result to Double is unsafe and should not be tried!
Thanks, DJClayworth!
NumberFormat is the way to go, but you should be aware of its peculiarities which crop up when your data is less than 100% correct.
I found the following usefull:
http://www.ibm.com/developerworks/java/library/j-numberformat/index.html
If your input can be trusted then you don't have to worry about it.
Just learning java and programming. Had similar question. Found something like this in my textbook:
Scanner sc = new Scanner(string);
double number = sc.nextDouble();
The book says that a scanner automatically decodes what's in a String variabel and that the Scanner class automatically adapts to the language of the set Locale, system Locale being the default, but that's easy to set to something else.
I solved my problem this way. Maybe this could work for the above issue instead of parsing?
Addition: The reason I liked this method was the fact that when using swing dialouge boxes for input and then trying to convert the string to double with parse I got a NumberFormatException. It turned out that parse exclusively uses US-number formatting while Scanner can handle all formats. Scanner made the input work flawlessly even with the comma (,) decimal separator. Since the most voted up answer uses parse I really don't see how it would solve this particular problem. You would have to input your numbers in US format and then convert them to your locale format. That's rather inconvenient when ones numeric keybord is fitted with a comma.
Now you're all free to shred me to pieces ;)
You use a NumberFormat. Here is one example, which I think looks correct.
Use NumberFormat.getNumberInstance(Locale)
This should be no problem using java.text.DecimalFormat.
Do you know which locale it is? Then you can use
DecimalFormat format = DecimalFormat.getInstance(theLocale);
format.parse(yourString);
this will even work for scientific notations, strings with percentage signs or strings with currency symbols.
Here is how you use parseDouble to convert a String to a Double:
doubleExample.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class doubleExample {
public static void main(String[] args) {
Double myDouble = new Double("0");
System.out.println("Please enter a number:");
try
{
//get the number from console
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
myDouble = Double.parseDouble(br.readLine());
}
//if invalid value was entered
catch(NumberFormatException ne)
{
System.out.println("Invalid value" + ne);
System.exit(0);
}
catch(IOException ioe)
{
System.out.println("IO Error :" + ioe);
System.exit(0);
}
System.out.println("Double value is " + myDouble);
}
}
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.
I want a filter to run through a string and eliminate all of the un-needed .0's from the doubles. I have already tried replaces, but cases like 8.02 turn into 82.
I have a feeling this has been done before, but I cannot find any help.
I am looking for a method that will take in a String, example: "[double] plus [double] is equal to [double]", where the [double] is a double that will need to be checked for the redundant decimal.
Thanks in advance!
let's say you have a string called s that contains text like you described. simply do:
s = s.replaceAll("([0-9])\\.0+([^0-9]|$)", "$1$2");
and you're done.
ok, so i edited this a couple of times. now it works though!
You can do this with a java.text.DecimalFormat object.
Can you not take away the trailing zeros before you construct them into your string? This way you could use the DecimalFormatter method someone posted earlier and then deleted.
NumberFormat formatter = new DecimalFormat("0.##");
String str = formatter.format("8.0200");
System.out.println(str);
Give them credit for the code if they come back.
The other posts assume you're working with a short string containing only decimal.
Assuming you're working with large strings of text, you can use Pattern/Matcher classes (I'm at work, so posting in a hurry. Check for errors)
Use this regex to replace:
/* >1 digits followed by a decimal and >1 zeros. Note capture group on first set of digits. This will only match decimals with trailing 0s, and not 8.0002 */
(\d+)\.0+
Replace with
/* First capture group */
$1
I'm unsure of the regex rules for Java, so use this as a concept to get what you want.
The following program will remove all trailing zeros from the fractional part of a double value. If your requirements are somewhat different, you may need to modify it slightly.
final public class Main
{
public static void main(String...args)
{
System.out.println("Enter how many numbers you want to check:->");
Scanner scan = new Scanner(System.in);
final double KEY_VALUE = 0.0;
final Double TOLERANCE = 0.000000000001d;
int n = scan.nextInt();
double[] a = new double[n];
for (int i = 0; i < n; i++)
{
a[i] = scan.nextDouble();
}
List<Double> newList = new ArrayList<Double>();
for (int k = 0; k < n; k++)
{
if (Math.abs(a[k] - KEY_VALUE) < TOLERANCE)
{
continue;
}
newList.add(a[k]);
}
System.out.println(newList);
}
}
You can specifically use DecimalFormat to truncate the specified number of decimal places, if you need such as follows.
double x=10.4555600500000;
DecimalFormat df=new DecimalFormat("#.##");
System.out.println(df.format(x));
Would return 10.46.
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.