Как округлить 0,745 до 0,75 с помощью BigDecimal.ROUND_HALF_UP?
Я попробовал следующее:
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 ????????????
но получили странные результаты. Почему?
Ответы
Ответ 1
Никогда не создавайте BigDecimals из float или double. Создайте их из ints или строк. плавает и удваивает свободную точность.
Этот код работает как ожидалось (я просто изменил тип от 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
}
Ответ 2
Используйте BigDecimal.valueOf(double d)
вместо new BigDecimal(double d)
. Последний имеет ошибки точности с помощью float и double.
Ответ 3
double doubleVal = 1.745;
double doubleVal1 = 0.745;
System.out.println(new BigDecimal(doubleVal));
System.out.println(new BigDecimal(doubleVal1));
выходы:
1.74500000000000010658141036401502788066864013671875
0.74499999999999999555910790149937383830547332763671875
Что показывает реальное значение двух удвоений и объясняет результат, который вы получаете. Как указывалось другими, не используйте двойной конструктор (кроме конкретного случая, когда вы хотите увидеть фактическое значение двойника).
Подробнее о двойной точности:
Ответ 4
Это может дать вам подсказку о том, что пошло не так.
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);
}
}
Проблема заключается в том, что ваш ввод (a double x=0.745;
) не может точно представлять 0.745. Это фактически сохраняет ценность немного ниже. Для BigDecimals
это уже ниже 0,745, поэтому округляется...
Попробуйте не использовать конструкторы BigDecimal(double/float)
.
Ответ 5
Для вашего интереса, сделайте то же самое с 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
, немного меньше, чем они появляются.