2016-05-29 1 views
1

Я уже посмотрел this asnwer.Как работает BigDecimal.valueOf (float)?

Я был немного сбит с толку поведением BigDecimal.valueOf(float). Вот пример:

System.out.println(BigDecimal.valueOf(20.2f)); //prints 20.200000762939453 

Поэтому

float f = BigDecimal.valueOf(20.2f) 
      .setScale(2, RoundingMode.UP) 
      .floatValue(); 
System.out.println(f); //prints 20.21 

Что defenitely не поведение я ожидал. Есть ли способ round up float правильно избегать таких ошибок?

+0

Взгляните (http://stackoverflow.com/questions/588004/is-floating-point-math- [Является плавающей точкой математике сломана?] сломаны). Числа с плавающей точкой с конечной точностью по существу не могут представлять некоторые значения. Это несколько похоже на то, как 1/3 невозможно представить точно в базе 10. Здесь '20.2f! = 20.2'. – Zong

+0

@ZongZhengLi Очень интересно. Итак, мы имеем дело с арифметикой с плавающей запятой и хотим сохранить точную точность, должны ли мы выполнять ROUND_EVEN в любое время, когда мы выполняем на них арифметические операции? – stella

+0

Каков ожидаемый результат? Мне кажется правильным, 20.200000762939453 округлен до двух знаков после запятой - 20.21. Вы можете попытаться установить масштаб на большее число с округлым, а затем установить на 2 с округлением – samgak

ответ

4

Для описания поплавка и как он использует выделенные биты см How many significant digits have floats and doubles in java?

BigDecimal прекрасно работает и - как и ожидалось - сохраняет все цифры он получил, но он не может угадать точность данный аргумент. Поэтому:

float f = 20.20f; 
    System.out.println("Float: "+f); 
    System.out.println("BigDecimal.valueOf: "+BigDecimal.valueOf(f)); 
    System.out.println("BigDecimal from value: "+new BigDecimal(f, MathContext.DECIMAL32)); 
    System.out.println("BigDecimal from string: "+new BigDecimal(""+f));; 

Печать:

Float: 20.2 
BigDecimal.valueOf: 20.200000762939453 
BigDecimal from value: 20.20000 
BigDecimal from string: 20.2 
Смежные вопросы