Форматирование десятичного числа

Я форматирую десятичное число, и у меня есть следующие критерии для его форматирования:

  • Число должно содержать не более двух знаков после запятой (10,1234=>10,12).
  • Если после запятой стоит только одна цифра, она заканчивается дополнительным 0 (10,5=>10,50).
  • Разделителем тысяч будет запятая (12345,2345 => 12 345,23)

Я написал следующую логику:

double x = Double.parseDouble(value.toString());
String dec = x % 1 == 0 ?  new java.text.DecimalFormat("###,###.##").format(x) : new java.text.DecimalFormat("###,###.00").format(x);

Сейчас печатает:

11111111111110.567=>11,111,111,111,110.57
111111111111110.567=>111,111,111,111,110.56
1111111111111110.567=>1,111,111,111,111,110.60
11111111111111110.567=>11,111,111,111,111,110
111111111111111110.567=>111,111,111,111,111,104
1111111111111111110.567=>1,111,111,111,111,111,170

Я не понимаю, почему поведение меняется. Как мне напечатать 1111111111111111110.567 как 1,111,111,111,111,111,110.57?


person Tapas Bose    schedule 20.08.2013    source источник


Ответы (2)


Проблема в том, что вы не можете представить 1111111111111111110.567 точно как double в первую очередь. (Вы даже не можете представить свое самое короткое значение точно, но неточность будет значительно возрастать по мере увеличения величины.)

В любом случае double имеет только около 17 значащих цифр полезных данных - вы пытаетесь получить 22 цифры.

Используйте BigDecimal, если вам нужна большая точность, но имейте в виду, что это изменит и другие вещи. В любом случае, какую ценность вы пытаетесь представить? Натуральные значения (веса, расстояния и т. д.) подходят для double; искусственные значения (особенно денежные значения) подходят для BigDecimal.

person Jon Skeet    schedule 20.08.2013

Мне удалось получить это (вы должны использовать BigDecimal):

import java.math.BigDecimal;
import java.text.NumberFormat;

public class Sandbox {
    public static void main(String[] args) {
        BigDecimal x = new BigDecimal("1111111111111111110.567");
        DecimalFormat formatter = new DecimalFormat("###,###.00");
        System.out.println(formatter.format(x));
    }
}

ВЫХОД:

1,111,111,111,111,111,110.57

Ссылки на ресурсы: DecimalFormat и BigDecimal

Еще одна вещь, вы должны ввести число BigDecimal как String, иначе это вызовет проблемы.

BigDecimal x = new BigDecimal(1111111111111111110.567) will output the following.

1,111,111,111,111,111,168.00
person Joban Dhillon    schedule 20.08.2013