2009-03-30 30 views
32

Tỷ lệ phần trăm của tôi bị cắt bớt theo hàm java.text.MessageFormat mặc định, làm cách nào để định dạng phần trăm mà không bị mất chính xác?Làm cách nào để bạn định dạng phần trăm phân số bằng java.text.MessageFormat

Ví dụ:

String expectedResult = "12.5%"; 
double fraction = 0.125; 

String actualResult = MessageFormat.format("{0,number,percent}", fraction); 
assert expectedResult.equals(actualResult) : actualResult +" should be formatted as "+expectedResult; 

Trả lời

47

Trông như thế này:

String actualResult = MessageFormat.format("{0,number,#.##%}", fraction); 

... đang làm việc.

EDIT: Để xem cách diễn giải của # và%, hãy xem javadoc của java.text.DecimalFormat.

CHỈNH SỬA 2: Và, vâng, an toàn cho quốc tế. Dấu chấm trong chuỗi định dạng được hiểu là dấu tách thập phân, không phải là dấu chấm cứng. :-)

+0

+1, điều này dễ dàng hơn so với những gì tôi đã làm. –

+0

Tuy nhiên, có thể không an toàn cho việc quốc tế hóa. Tôi không biết chắc chắn. –

+0

Luôn luôn có những người địa phương nguy hiểm phá vỡ một số chuỗi định dạng, nhưng nếu không tôi không thể nghĩ về bất kỳ mối quan tâm nào khác ... –

5

Làm thế nào về

DecimalFormat f = new DecimalFormat("###.#"); 
System.out.println(f.format(12.5)); 

Định dạng char '#' không in 0 như vắng mặt. 12,5 -> "12,5", 12,0 -> "12", không phải "12,0". Tất nhiên, bạn có thể thiết lập trình định dạng của mình với ví dụ: "###, ###. ##", hundreths place sẽ chỉ hiển thị nếu bạn cần độ chính xác.

3

Bạn nhận ra rằng "expectedResult == actualResult" sẽ luôn là sai, phải không?

Dù sao, giải pháp tốt nhất tôi có thể tìm là đặt trình định dạng rõ ràng. Đây là mã tôi thử nghiệm:

String expectedResult = "12.5%"; 
double fraction = 0.125; 
MessageFormat fmt = new MessageFormat("{0,number,percent}"); 
NumberFormat nbFmt = NumberFormat.getPercentInstance(); 
nbFmt.setMaximumFractionDigits(1); // or 2, or however many you need 
fmt.setFormatByArgumentIndex(0, nbFmt); 
String actualResult = fmt.format(new Object[] {fraction}); 
assert expectedResult.equals(actualResult) : actualResult +" is getting rounded off"; 
+0

hah, vâng. xin lỗi vì điều đó. Tôi đã sửa lại ví dụ. – Lorin

48

Tôi nghĩ rằng cách thích hợp để làm điều đó là như sau:

NumberFormat percentFormat = NumberFormat.getPercentInstance(); 
percentFormat.setMaximumFractionDigits(1); 
String result = percentFormat.format(0.125); 

Nó cũng cần quốc tế hóa vào tài khoản. Ví dụ trên máy tính của tôi với locale hungarian tôi đã nhận "12,5%" như mong đợi. Việc khởi tạo percentFormat là NumberFormat.getPercentInstance(Locale.US) mang lại "12.5%" tất nhiên.

+1

Trong Android, nó hoạt động như một sự quyến rũ! Cảm ơn bạn. – Rainbowbreeze

2

Nếu quốc tế hóa là một mối quan tâm:

// get locale from somewhere. default is usually a bad idea, especially 
// if running in a app server 
Locale locale = Locale.getDefault(); 
NumberFormat fmt = NumberFormat.getPercentInstance(locale); 
// the question requires 1 digit for fractional part 
// therefore set both, minimum and maximum digit count 
fmt.setMinimumFractionDigits(1); 
fmt.setMaximumFractionDigits(1); 
// set grouping, if you expect large values 
// notabene: not all languages use 3 digits per group 
fmt.setGroupingUsed(true); 
// output the example of the original question 
System.out.println(fmt.format(0.125)); 

Tỷ lệ số định dạng gắn thêm một không gian và các ký hiệu phần trăm đến đầu ra trong miền địa phương tôi biết. Tôi không biết, cho dù vị trí của dấu phần trăm là trước các chữ số trong các ngôn ngữ khác (ví dụ từ phải sang trái).

2

Giải pháp của tôi hiển thị dưới dạng nhiều chữ số thập phân khi tỷ lệ được đặt trên Số đã cho. Đơn vị được thử nghiệm với nhiều loại nguyên thủy và Number.

/** 
* Formats the given Number as percentage with necessary precision. 
* This serves as a workaround for {@link NumberFormat#getPercentInstance()} which does not renders fractional 
* digits. 
* 
* @param number 
* @param locale 
* 
* @return 
*/ 
public static String formatPercentFraction(final Number number, final Locale locale) 
{ 
    if (number == null) 
     return null; 

    // get string representation with dot 
    final String strNumber = NumberFormat.getNumberInstance(Locale.US).format(number.doubleValue()); 
    // create exact BigDecimal and convert to get scale 
    final BigDecimal dNumber = new BigDecimal(strNumber).multiply(new BigDecimal(100)); 

    final NumberFormat percentScaleFormat = NumberFormat.getPercentInstance(locale); 
    percentScaleFormat.setMaximumFractionDigits(Math.max(0, dNumber.scale())); 

    // convert back for locale percent formatter 
    return percentScaleFormat.format(dNumber.multiply(new BigDecimal(0.01))); 
} 
Các vấn đề liên quan