Как округлить 0,745 до 0,75, используя BigDecimal.ROUND_HALF_UP?

java bigdecimal rounding

114613 просмотра

5 ответа

375 Репутация автора

Я попробовал следующее,

   double doubleVal = 1.745;
   double doubleVal1 = 0.745;
   BigDecimal bdTest = new BigDecimal(  doubleVal);
   BigDecimal bdTest1 = new BigDecimal(  doubleVal1 );
   bdTest = bdTest.setScale(2, BigDecimal.ROUND_HALF_UP);
   bdTest1 = bdTest1.setScale(2, BigDecimal.ROUND_HALF_UP);
   System.out.println("bdTest:"+bdTest); //1.75
   System.out.println("bdTest1:"+bdTest1);//0.74    problemmmm ????????????  

но получил странные результаты. Почему?

Автор: aliplane Источник Размещён: 17.09.2012 01:39

Ответы (5)


2 плюса

7390 Репутация автора

Это может дать вам подсказку о том, что пошло не так.

import java.math.BigDecimal;

public class Main {
    public static void main(String[] args) {
        BigDecimal bdTest = new BigDecimal(0.745);
        BigDecimal bdTest1 = new BigDecimal("0.745");
        bdTest = bdTest.setScale(2, BigDecimal.ROUND_HALF_UP);
        bdTest1 = bdTest1.setScale(2, BigDecimal.ROUND_HALF_UP);
        System.out.println("bdTest:" + bdTest);
        System.out.println("bdTest1:" + bdTest1); 
    }
}

Проблема в том, что ваш вход (а double x=0.745;) не может точно представлять 0,745. Это на самом деле сохраняет значение немного ниже. Ибо BigDecimalsэто уже ниже 0,745, поэтому он округляется вниз ...

Старайтесь не использовать BigDecimal(double/float)конструкторы.

Автор: brimborium Размещён: 17.09.2012 01:45

89 плюса

23762 Репутация автора

Решение

Никогда не создавайте BigDecimals из чисел с плавающей точкой или двойных. Построить их из целых или строк. плавает и удваивает потерю точности.

Этот код работает как ожидалось (я только что изменил тип с double на String):

public static void main(String[] args) {
  String doubleVal = "1.745";
  String doubleVal1 = "0.745";
  BigDecimal bdTest = new BigDecimal(  doubleVal);
  BigDecimal bdTest1 = new BigDecimal(  doubleVal1 );
  bdTest = bdTest.setScale(2, BigDecimal.ROUND_HALF_UP);
  bdTest1 = bdTest1.setScale(2, BigDecimal.ROUND_HALF_UP);
  System.out.println("bdTest:"+bdTest); //1.75
  System.out.println("bdTest1:"+bdTest1);//0.75, no problem
}
Автор: Augusto Размещён: 17.09.2012 01:45

11 плюса

263942 Репутация автора

double doubleVal = 1.745;
double doubleVal1 = 0.745;
System.out.println(new BigDecimal(doubleVal));
System.out.println(new BigDecimal(doubleVal1));

выходы:

1.74500000000000010658141036401502788066864013671875
0.74499999999999999555910790149937383830547332763671875

Который показывает реальное значение двух двойных и объясняет полученный результат. Как отмечают другие, не используйте конструктор double (кроме конкретного случая, когда вы хотите увидеть фактическое значение double).

Подробнее о двойной точности:

Автор: assylias Размещён: 17.09.2012 01:48

2 плюса

463335 Репутация автора

Для вашего интереса, сделать то же самое с double

double doubleVal = 1.745;
double doubleVal2 = 0.745;
doubleVal = Math.round(doubleVal * 100 + 0.005) / 100.0;
doubleVal2 = Math.round(doubleVal2 * 100 + 0.005) / 100.0;
System.out.println("bdTest: " + doubleVal); //1.75
System.out.println("bdTest1: " + doubleVal2);//0.75

или просто

double doubleVal = 1.745;
double doubleVal2 = 0.745;
System.out.printf("bdTest: %.2f%n",  doubleVal);
System.out.printf("bdTest1: %.2f%n",  doubleVal2);

обе печати

bdTest: 1.75
bdTest1: 0.75

Я предпочитаю сделать код максимально простым. ;)

Как отмечает @mshutov, вам нужно добавить немного больше, чтобы половина значений всегда округлялась. Это потому, что числа вроде 265.335немного меньше, чем кажутся.

Автор: Peter Lawrey Размещён: 17.09.2012 02:00

10 плюса

133 Репутация автора

Используйте BigDecimal.valueOf(double d)вместо new BigDecimal(double d). Последний имеет ошибки точности по плавающей и двойной.

Автор: admoca60 Размещён: 12.08.2014 04:03
Вопросы из категории :
32x32