I have an Android application which does some basic mathematics.
Example
try {
NumberFormat nf = NumberFormat.getNumberInstance();
DecimalFormat df = (DecimalFormat) nf;
a = Float.parseFloat(vw3.getText().toString());
f = Float.parseFloat(vw5.getText().toString());
c = a / 100;
d = c * 1.036f;
e = f / 100;
g = e * 1.24f;
h = d + g;
String str1 = String.valueOf(df.format(h));
vw7.setText(str1);
} catch (NumberFormatException f) {
a = (0);
}
}
When the user is in the USA the calculations work fine and format fine. Well as you would expect. The 1,000.00 format where the grouping is by comma and separator is by decimal point. When a user is in France, the grouping is different and the separator is also different. Using the 1,000.00 example, in France the number would be formatted like this 1 000,00. A space is the grouping separator and the comma is the decimal separator. This causes a problem when you try and run a calculation and you will get a NumberFromatException (NFE). And I anticipated a NFE issue and catch it and replace the possible cause with the correct number. However, replacing any comma with a space and any period with a comma will also produce a NFE.
Example
try {
NumberFormat nf = NumberFormat.getNumberInstance();
DecimalFormat df = (DecimalFormat) nf;
a = Float.parseFloat(vw3.getText().toString().replace(",",""));
f = Float.parseFloat(vw5.getText().toString().replace(",",""));
c = a / 100;
d = c * 1.036f;
e = f / 100;
g = e * 1.24f;
h = d + g;
String str1 = String.valueOf(df.format(h));
vw7.setText(str1);
} catch (NumberFormatException f) {
a = (0);
}
}
EDIT - As suggested by Peter O. I have tried parsing the number with a locale aware means.
Example
NumberFormat.getNumberInstance().parse(string);
Or
NumberFormat df = NumberFormat.getNumberInstance();
String value = "10,40 €";
Number valueParsed = df.parse(value);
vw7.setText(valueParsed);
Will produce a "Bad Class" illegalargument.
I am looking for a solution to where I can do the calculations in an acceptable manner within the apps programming regardless of the locale and then later format the results to the locale. The question could be or is, do you force a locale for your calculations and then format the results for the locale?
If this is the code you are using and your strings will have the currency symbol. In this case € the EURO symbol.
Your example:
NumberFormat df = NumberFormat.getNumberInstance();
String value = "10,40 €";
Number valueParsed = df.parse(value);
vw7.setText(valueParsed);
so that value always has a currency symbol you need to use
NumberFormat df= NumberFormat.getCurrencyInstance();
instead of the .getNumberInstance(). This worked on my system which is currently set so that the € symbols is the default currency symbol. You will have to try it on a system that has the $ currency symbol in order to verify that it works there, also.
I'm creating a Calculator software. In the text field as I'm typing, the whole expression appears as one string (and I want to keep it this way). Here's a demo:
I want it to be formatted like this:
NUMBERS - ###.###.###,###### (Grouping them into 3 digit groups, displaying fractions ONLY when needed and only up to 6 digits.)
Operators and Parenthesis - ###×(###-###)/### (Should not cause any formatting errors or problems. I don't care if there is or there isn't a space inbetween the numbers and operators/parenthesis.)
Here's the above example in the correct format:
1.000×(5-3)/2
I also want it to automatically update the formatting as I'm typing.
Sofar I tried using JFormattedTextField with MaskFormatters and NumberFormat but neither of them worked as (described above) I wanted to.
NumberFormat version.
public class Frame {
private NumberFormat numberFormat = NumberFormat.getInstance();
private JFormattedTextField textField = new JFormattedTextField(numberFormat);
}
MaskFormatter version.
public class Frame {
private MaskFormatter maskFormat;
private JFormattedTextField textField;
public Frame() {
try {
maskFormat = new MaskFormatter("###.###.###,######");
} catch (ParseException e) {
e.printStackTrace();
}
textField = new JFormattedTextField(maskFormat);
}
}
I managed to format the result using DecimalFormat but I don't want only the result to be formatted.
Formatting the result.
DecimalFormat resultFormat = new DecimalFormat("###,###,###.######");
String result = resultFormat.format(Parser.evaluate(expression));
textField.setText(result);
When I calculate 5/3 the result is:
Just as I wanted.
Sorry for such a detailed and long post, any help is greatly appreciated!
Try this.
DecimalFormat resultFormat = new DecimalFormat("###,###,###.######");
Pattern numberPattern = Pattern.compile("\\d+(\\.\\d+)?");
String s = "1000×(5-3)/2";
Matcher m = numberPattern.matcher(s);
StringBuffer sb = new StringBuffer();
while (m.find()) {
double value = Double.parseDouble(m.group());
String formatted = resultFormat.format(value);
m.appendReplacement(sb, formatted);
}
m.appendTail(sb);
System.out.println(sb);
// -> 1,000×(5-3)/2
I'm using a NumberFormat instance to parse text using default locale.
If a string is not a valid numeric value, I have to return 0. The problem is that parse method,according to Javadocs:
Parses text from the beginning of the given string to produce a
number. The method may not use the entire text of the given string.
So, if I parse (I'm using italian locale) "BAD 123,44" I correctly get a ParseException and return 0, but if I parse "123,44 BAD", I get a value of 123.44, while I have to return 0 in this case.
And worse, if I parse "123.44 BAD", I get value 12344!
class RateCellReader {
public static final NumberFormat NUMBER_FORMAT =
NumberFormat.getNumberInstance(Locale.getDefault());
...
try {
number = NUMBER_FORMAT.parse(textValue);
} catch (ParseException e) {
number = 0;
}
...
}
How can I do an exact parse of text, or check if text correctly represent a number in default locale?
EDIT:
Getting inspired by the response linked by #yomexzo, I changed my code like this:
class RateCellReader {
public static final NumberFormat NUMBER_FORMAT =
NumberFormat.getNumberInstance(Locale.getDefault());
...
ParsePosition pos = new ParsePosition(0);
number = NUMBER_FORMAT.parse(textValue,pos);
if (textValue.length() != pos.getIndex())
number = 0;
...
}
How about this
boolean isValid;
try {
Number n = NUMBER_FORMAT.parse(s1);
String s2 = NUMBER_FORMAT.format(n);
isValid = s1.equals(s2);
}catch(ParseException e) {
isValid = false;
}
I am using NumberFormat.getCurrencyInstance(myLocale) to get a custom currency format for a locale given by me. However, this always includes the currency symbol which I don't want, I just want the proper currency number format for my given locale without the currency symbol.
Doing a format.setCurrencySymbol(null) throws an exception..
The following works. It's a bit ugly, but it fulfils the contract:
NumberFormat nf = NumberFormat.getCurrencyInstance();
DecimalFormatSymbols decimalFormatSymbols = ((DecimalFormat) nf).getDecimalFormatSymbols();
decimalFormatSymbols.setCurrencySymbol("");
((DecimalFormat) nf).setDecimalFormatSymbols(decimalFormatSymbols);
System.out.println(nf.format(12345.124).trim());
You could also get the pattern from the currency format, remove the currency symbol, and reconstruct a new format from the new pattern:
NumberFormat nf = NumberFormat.getCurrencyInstance();
String pattern = ((DecimalFormat) nf).toPattern();
String newPattern = pattern.replace("\u00A4", "").trim();
NumberFormat newFormat = new DecimalFormat(newPattern);
System.out.println(newFormat.format(12345.124));
Set it with an empty string instead:
DecimalFormat formatter = (DecimalFormat) NumberFormat.getCurrencyInstance(Locale.US);
DecimalFormatSymbols symbols = formatter.getDecimalFormatSymbols();
symbols.setCurrencySymbol(""); // Don't use null.
formatter.setDecimalFormatSymbols(symbols);
System.out.println(formatter.format(12.3456)); // 12.35
The given solution worked but ended up lefting some whitespaces for Euro for example.
I ended up doing :
numberFormat.format(myNumber).replaceAll("[^0123456789.,]","");
This makes sure we have the currency formatting for a number without the currency or any other symbol.
Just use NumberFormat.getInstance() instead of NumberFormat.getCurrencyInstance() like follows:
val numberFormat = NumberFormat.getInstance().apply {
this.currency = Currency.getInstance()
}
val formattedText = numberFormat.format(3.4)
I still see people answering this question in 2020, so why not
NumberFormat nf = NumberFormat.getInstance(Locale.US);
nf.setMinimumFractionDigits(2); // <- the trick is here
System.out.println(nf.format(1000)); // <- 1,000.00
Maybe we can just use replace or substring to just take the number part of the formatted string.
NumberFormat fmt = NumberFormat.getCurrencyInstance(Locale.getDefault());
fmt.format(-1989.64).replace(fmt.getCurrency().getSymbol(), "");
//fmt.format(1989.64).substring(1); //this doesn't work for negative number since its format is -$1989.64
DecimalFormat df = new DecimalFormat();
df.setMinimumFractionDigits(2);
String formatted = df.format(num);
Works with many types for num, but don't forget to represent currency with BigDecimal.
For the situations when your num can have more than two digits after the decimal point, you could use df.setMaximumFractionDigits(2) to show only two, but that could only hide an underlying problem from whoever is running the application.
Most (all?) solutions provided here are useless in newer Java versions. Please use this:
DecimalFormat formatter = (DecimalFormat) DecimalFormat.getCurrencyInstance(Locale.forLanguageTag("hr"));
formatter.setNegativeSuffix(""); // does the trick
formatter.setPositiveSuffix(""); // does the trick
formatter.format(new BigDecimal("12345.12"))
Two Line answer
NumberFormat formatCurrency = new NumberFormat.currency(symbol: "");
var currencyConverted = formatCurrency.format(money);
In TextView
new Text('${formatCurrency.format(money}'),
NumberFormat numberFormat = NumberFormat.getCurrencyInstance(Locale.UK);
System.out.println("getCurrency = " + numberFormat.getCurrency());
String number = numberFormat.format(99.123452323232323232323232);
System.out.println("number = " + number);
here the code that with any symbol (m2, currency, kilos, etc)
fun EditText.addCurrencyFormatter(symbol: String) {
this.addTextChangedListener(object: TextWatcher {
private var current = ""
override fun afterTextChanged(s: Editable?) {
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
if (s.toString() != current) {
this#addCurrencyFormatter.removeTextChangedListener(this)
val cleanString = s.toString().replace("\\D".toRegex(), "")
val parsed = if (cleanString.isBlank()) 0.0 else cleanString.toInt()
val formatter = DecimalFormat.getInstance()
val formated = formatter.format(parsed).replace(",",".")
current = formated
this#addCurrencyFormatter.setText(formated + " $symbol")
this#addCurrencyFormatter.setSelection(formated.length)
this#addCurrencyFormatter.addTextChangedListener(this)
}
}
})
}
-use with-
edit_text.addCurrencyFormatter("TL")
In a function like this
fun formatWithoutCurrency(value: Any): String {
val numberFormat = NumberFormat.getInstance()
return numberFormat.format(value)
}
there is a need for a currency format "WITHOUT the symbol", when u got huge reports or views and almost all columns represent monetary values, the symbol is annoying, there is no need for the symbol but yes for thousands separator and decimal comma.
U need
new DecimalFormat("#,##0.00");
and not
new DecimalFormat("$#,##0.00");
Please try below:
var totale=64000.15
var formatter = new Intl.NumberFormat('de-DE');
totaleGT=new Intl.NumberFormat('de-DE' ).format(totale)
I'm using DecimalFormat to parse / validate user input. Unfortunately it allows characters as a suffix while parsing.
Example code:
try {
final NumberFormat numberFormat = new DecimalFormat();
System.out.println(numberFormat.parse("12abc"));
System.out.println(numberFormat.parse("abc12"));
} catch (final ParseException e) {
System.out.println("parse exception");
}
Result:
12
parse exception
I would actually expect a parse exception for both of them. How can I tell DecimalFormat to not allow input like "12abc"?
From the documentation of NumberFormat.parse:
Parses text from the beginning of the given string to produce a number. The method may not use the entire text of the given string.
Here is an example that should give you an idea how to make sure the entire string is considered.
import java.text.*;
public class Test {
public static void main(String[] args) {
System.out.println(parseCompleteString("12"));
System.out.println(parseCompleteString("12abc"));
System.out.println(parseCompleteString("abc12"));
}
public static Number parseCompleteString(String input) {
ParsePosition pp = new ParsePosition(0);
NumberFormat numberFormat = new DecimalFormat();
Number result = numberFormat.parse(input, pp);
return pp.getIndex() == input.length() ? result : null;
}
}
Output:
12
null
null
Use the parse(String, ParsePosition) overload of the method, and check the .getIndex() of the ParsePosition after parsing, to see if it matches the length of the input.