String.format uses comma instead of point - android

My app is working on many devices without problems so far. But now I got my new Galaxy Tab with Android 3.2 where it crashes all the time. I found out that the problem was a float in an EditText.
I am using myEditText.setText(String.format("%.1f", fMyFloat)); to put the float in the EditText. But somehow the float on my 3.2 Galaxy Tab is generated with a comma instead of a point. When I read the EditText back the app crashes of course, telling me that this is no valid float because of the comma...
What is going wrong here?

Convert float to string..
From the documentation of String.format:
String.format(String format, Object... args)
Returns a localized formatted string, using the supplied format and arguments, using the user's default locale.
The quoted text above means that the output of String.format will match the default locale the user uses.
As an example a comma would be used as the decimal-point-delimiter if it's a user using Swedish locale, but a dot if it's using an American.
If you'd like to force what locale is going to be used, use the overload of String.format that accepts three parameters:
String.format (Locale locale, String format, Object... args)
Convert string to float..
Parsing an arbitrary string into a float using the default locale is quite easy, all you need to do is to use DecimalFormat.parse.
Then use .parse to get a Number and call floatValue on this returned object.

Your format call on your Galaxy Tab uses some default Locale which in turn uses , for floats. You could use String.format(Locale,String,...) version with specific locale to make things work.
Or you should've used same locale both for parsing and formatting the number. So you should probably go with NumberFormat to format and parse your floats.

String.format uses the locale you are in. You should do something like this if you want a dot:
NumberFormat formatter = NumberFormat.getInstance(Locale.US);
myEditText.setText(formatter.format(fMyFloat);
Have a look into NumberFormat for more formatting options

Use below code it's works for me:
NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
DecimalFormat df = (DecimalFormat)nf;
df.applyPattern(pattern);
String output = df.format(value);
System.out.println(pattern + " " + output + " " + loc.toString());

Summing up previous answers, an easy way to have the dot instead of the comma in all country, is this:
myEditText.setText(Locale.CANADA, String.format("%.1f", fMyFloat));
And you will have your String formatted with the dot

Related

Android Java.Lang Locale Number Format I/O Asymmetry Problem

Historically the Android phones sold in South Africa provided English.US and English.UK locale support, but recently English.ZA (South Africa) has made an appearance, on Android 9.0 Samsung Galaxy A10, for example.
This particular Locale is showing asymmetric treatment of number formats, using the Locale.DE (German/Dutch) convention when converting Floats and Doubles into character strings[*1], but raising Java.Lang.NumberFormatException when reading back the self-same generated strings. For instance:
// on output
Float fltNum = 1.23456F;
System.out.println(String.format(Locale.getDefault(),"%f",fltNum)); // prints '1,23456'
// on Input
String fltStr = "1,23456";
Float fltVal;
fltVal = Float(fltStr); // generates NumberFormatException
fltVal = Float.parseFloat(fltStr); // also generates NumberFormatException
// Giving the compiler Float hints fltStr = "1,23456F" does not help
// Only fltStr = '1.23456' converts into a Float.
The temptation would be to swap decimal separators on reads, but that is the task of Float.parseFloat(), a not of the programer, for doing so shall again break other Locale.DE-likes, such as Locale.ID (Indonesia) which my App supports.
My additional question directed more at Locale arbitrators is: Does English.ZA not imply English conformant as would say German.NA (Namibia) be German conformant? One would think the natural designation for this particular number conversion would be Dutch.ZA (colloquially 'Afrikaans'), for Dutch conformance, but Android designates it as English.ZA?
NB (*1) This Android English.ZA conforms only partially as it does not produce either the German point group separator or the local clerical (pen-and-paper) space character group separator.
Apologies for using 'Answer' to respond to diogenesgg's comment suggestion:
"Hi, please take a look at this answer stackoverflow.com/questions/5233012/…. TL/DR."
In it I found a few gems -
(1)
NumberFormat f = NumberFormat.getInstance(Locale.getDefault());
if (f instanceof DecimalFormat) {
((DecimalFormat) f).setDecimalSeparatorAlwaysShown(true);
}
But this is neutral and not value-specific so I added after the above,
(2) Given:
String axisValue("some-float-value-rendered as string");
NumberFormat nf = new DecimalFormat(axisValue);
Which I incorporate sequentially:
NumberFormat nf = new DecimalFormat(axisValue);
Number n;
if(nf instanceof DecimalFormat){
try{
n = nf.parse (axisValue);
axisComponent = (Double) n;
} catch (java.text.ParseException jtpe) {
jtpe.printStackTrace();
}
}
Notice the need to cast the Number n to Double.
This worked mostly under the problematic Locale English.ZA, until the value 0,00000 showed up.
For the string value "0,00000", NumberFormat decides Number n is a Long, and the system throws a (Long to Double) CastException.
I tried to trick NumberFormat in all ways I can to view 0 as a Float or Double to no avail, so 0 is a border problem that Number (NumberFormat.DecimalFormat) does not tolerate.
But this NumberFormat workaround does not resolve the assymmetry problem of Android 9 Locale.English(ZA).DecimalFormat emitting Locale.DE (comma decimal separator) but parsing only System.Primitives (decimal dot separator).
Incidentally, getting past the DecimalFormat problem exposed a myriad of other problems under this new-fangled English.ZA, of my App assuming system primitives working equally well with native resources. Well semantics so used require string comparison to work between primitive and native!
For example system file Primitive path names rendered in Native generating 'file not found', or even more problematic, using primitive string keys semantically only to being rendered meaningless on Native lookup.
I'm not sure which is the lesser evil, assymmetric locale English.ZA or my use of Primitives in semantics to thrust upon Natives. A futile exercise!
Right now I'm embarking on separating system primitives, including their semantic variants from ANY Native language resource strings ...
My lifetime of programming under system primitives needs an overall makeover.
Maybe I can keep an Assets repository for the primitives (resource or semantic) and have Natives look that up for system resources or for semantic Meaning.

How to format a number as currency using only currency code?

My business problem is as follows: I have a currency code (e.g. "USD") and a number (either float or integer, I can parse either way) and I need to format this number to a currency string using the currency code. For example, 124.3222 and "USD" should create the string "$124.32".
I can create a Currency instance using Currency.getInstance(String), which gives me the symbol and some other information. However, it does not provide any way to format the number as a string. On the other side of the problem, NumberFormat contains several static methods that return a NumberFormat instance capable of doing what I need (e.g. NumberFormat.getCurrencyInstance()).
The problem with NumberFormat is they are all centered around either the default locale, or a passed-in Locale. Given the nature of this app, locale is meaningless. There is no correlation between locale and the currency I need to format as a string. I can use neither the default locale, nor do I have any sort of locale identifier ISO value. All I have is the currency code.
It seems like I'm so close yet so far. There is (in my opinion) an odd disconnect between Currency and the NumberFormat.getCurrencyInstance. Currency can parse a currency code but not locale and cannot format strings, while Locale cannot parse a currency code but can format strings. Am I missing something here?
Edit: I should clarify that I can manually format the number using the symbol and decimal count provided by Currency instance, but I don't see how to figure out where to put the symbol in the string. At any rate, it seems like I should use the built-in currency formatting whenever possible.
I discovered there is a setCurrency() method on NumberFormat. So what I am doing is calling NumberFormat.getCurrencyInstance() so I get a formatter for my locale, and then calling setCurrency() on it for the currency I need to format. This seems to do what I need.

Android - What's the difference between Locale.toString() and Locale.toLanguageTag()?

I have a piece of code where I'm trying to change the language in my app, using a Spinner View Component. While working with this, I've come to realize that I'm probably not using the most smooth method, but more intrestingly, I've noticed that two strings that LOOK the same are not equal when compared. Why is it like this, and how should I do if I want to "check" if the language is a certain one?
if (myLocale.toLanguageTag()=="sv")
{
//Changing language from Swedish to English
}
else
{
Toast.makeText(parent.getContext(),
myLocale.toString(), Toast.LENGTH_SHORT).show();
//Here, the toast will tell me what myLocale.toString is "sv",
//and so is myLocale.toLanguageTag(). Yet they are not equal...
}
As stated in the documentation:
Locale.toString() returns a string representation of this Locale object, consisting of language, country, variant, script, and extensions, whatever is available, as below:
language + "_" + country + "_" + (variant + "_#" | "#") + script + "-" + extensions
Language is always lower case, country is always upper case, script is always title case, and extensions are always lower case.
for example en_US, en
Whereas Locale.toLanguageTag() returns you the same stuff (language, country, and variant), but as a tag. Here Tag means some code given for language, country and variant defined by some IETF's BCP 47 standard (BCP = 'Best Current Practice').
for example en-US
The only difference I can see is the _ and - or perhaps some language/country codes too.
In nutshell, both of them return String; one returns a normal string representation of the Locale whereas the later returns a string as a well-formed IETF BCP 47 language tag representing the locale.
The documentation also suggests using toString only in debugging mode:
This behavior is designed to support debugging and to be compatible with previous uses of toString that expected language, country, and variant fields only. To represent a Locale as a String for interchange purposes, use toLanguageTag().
Hope it helps.
Use .equals() for strings comparison.
A good explanation can be found here
if ("sv".equals(myLocale.toLanguageTag()))

Decimal Format separator

I have a problem with formatting decimal values for localizing in Spanish (and other European languages, as well) when the decimal separator for Spain comes out as a comma ,.
How can I get the decimal separator as dot .?
Here is the code I used for formatting a decimal number
DecimalFormat twoDecimalForm = null;
twoDecimalForm = new DecimalFormat("#.##");
DecimalFormatSymbols.getInstance().setDecimalSeparator('.');
String valueInDecimal = twoDecimalForm.format(0.005 * progressValue);
//Exception here
Log.d(TAG,"valueInDecimal" + Double.valueOf(valueInDecimal));
I am getting a comma , instead of of a dot .
A workaround can be replace the comma with ..
But is there any other solution?
If you getting data from web then ask your web developer to pass data as per your requirement, then your problem gets resolved or you can go with replace option.

How to prevent default language to be forced when using string format

So I Have a TextView in my calculator app that I eventually display the results in it ...
It works ... but recently during the testing I found out that if The Default Language of That device is set to a non-english language (for example arabic or farsi) numbers in TextView get to be shown in that specific language (not english) and in a completely different format !!
I used this code to generate the result
result = String.format("%.4f", mResultBeforeFormatting);
resultTextView.settext(result);
also to note is that if I set the TextView with a hard coded string the issue doesn't happen
resultTextView.settext("343");
The formats used by the String.format method will by default be the formats specified by the device's default locale.
If you want to force the use of a specific locale, use the String.format method that accepts a locale parameter.
For example:
result = String.format(Locale.ENGLISH, "%.4f", mResultBeforeFormatting);

Categories

Resources