Reputation: 77
I'm trying to use DecimalFormat to convert the Decimal separator of a double value while retaining all decimals of the original number. DecimalFormatter accepts a pattern in the format: "0.##", for example. Since I have to use numbers with varying decimals, this will not work, however, since the number of decimals always needs to be specified in the pattern.
I am looking for a way to get around this.
I've tried String.format. DecimaFormatter and NumberFormatter
What I would like ideally is something along the lines of:
private static final ThreadLocal< DecimalFormat > formatter = new ThreadLocal< DecimalFormat >()
{
@Override
protected DecimalFormat initialValue()
{
// n should be any number of decimals without having to specify them.
return new DecimalFormat("0.0#n");
}
};
Some examples:
DecimalFormat df = new DecimalFormat("0.0##");
System.out.println(df.format(2.456))
System.out.println(df.format(2.1));
Result:
2,456 -> Good
2,100 -> Not good
I want to set a pattern/regex which will work for doubles of any number of digits after the decimal separator like:
2,456 -> Good
2,1 -> Good
3,3453456345234 -> Good
Upvotes: 3
Views: 2726
Reputation: 159086
DecimalFormat
has 16 setter methods for controlling the output. The pattern string you specify in the constructor is just a convenient way to set most of those values.
To control the locale of the output, you can specify the DecimalFormatSymbols
, either in the constructor or in a setter method.
Since you want unlimited decimal places, and it seems you want at least one decimal place, you need to call a setter method, because specifying unlimited is not possible with the pattern string.
Example
private static void test(Locale locale) {
DecimalFormat fmt = new DecimalFormat("0.0", DecimalFormatSymbols.getInstance(locale));
//fmt.setMaximumIntegerDigits(Integer.MAX_VALUE); // already set by pattern
//fmt.setMinimumIntegerDigits(1); // already set by pattern
//fmt.setMinimumFractionDigits(1); // already set by pattern
fmt.setMaximumFractionDigits(Integer.MAX_VALUE);
//fmt.setGroupingUsed(false); // already set by pattern
System.out.println(locale.toLanguageTag() + " (" + locale.getDisplayLanguage(Locale.US) +
" - " + locale.getDisplayCountry(Locale.US) + ")");
System.out.println(" " + fmt.format(123456789));
System.out.println(" " + fmt.format(2.456));
System.out.println(" " + fmt.format(2.1));
System.out.println(" " + fmt.format(3.3453456345234));
}
public static void main(String[] args) {
test(Locale.US);
test(Locale.GERMANY);
test(Locale.forLanguageTag("ar-EG"));
}
Output (OpenJDK 11.0.1)
en-US (English - United States)
123456789.0
2.456
2.1
3.3453456345234
de-DE (German - Germany)
123456789,0
2,456
2,1
3,3453456345234
ar-EG (Arabic - Egypt)
١٢٣٤٥٦٧٨٩٫٠
٢٫٤٥٦
٢٫١
٣٫٣٤٥٣٤٥٦٣٤٥٢٣٤
Upvotes: 0
Reputation: 109547
So you have
double[] floats = { 3.20, 4.500, 6.34, 1.0000 };
BigDecimal[] fixeds = {
new BigDecimal("3.20"),
new BigDecimal("4.500"),
new BigDecimal("6.34"),
new BigDecimal("1.0000")
};
and want to format them as such, but localized.
The good news is that fixed point numbers with BigDecimal maintain a precision (using the string constructor). The bad news is that floating point is alwaya an approximation, by a sum of (negative) powers of 2. So 3.20 might actually be 3.19999987 or 3.20000043.
They have no fixed decimals. Even without approximation error 3.2 == 3.20 == 3.200.
So convert to BigDecimal (quite ugly), and get rid of the approximation errors: 1000*3.2 != 3200.0.
BigDecimal value = new BigDecimal("5.1000");
NumberFormat df = NumberFormat.getInstance(Locale.KOREA);
df.setMinimumFractionDigits(value.getScale()); // 4
String s = df.format(value);
Upvotes: 0
Reputation: 1074148
Numbers in Java (and just numbers, generally) don't have a set number of decimal places. 1.1
, 1.10
, and 1.100
are all exactly the same number.
You could find out how many places default formatting would use, e.g.:
String str = num.toString();
int decimal = str.indexOf('.');
int places = decimal <= 0 ? 0 : str.length - decimal;
...and then specify that many places when using the formatter.
Upvotes: 3