BigDecimal, я полагаю, что он знаком многим людям, и многие люди знают его использование.Это тип, представленный в пакете java.math, который можно использовать для точных операций.
Многие знают, что в таких сценариях, как представление суммы и вычисление суммы, нельзя использовать такие типы, как double и float, но следует использовать BigDecimal с большей поддержкой точности.
Поэтому во многих платежных, электронной коммерции, финансах и других сферах бизнеса BigDecimal используется очень часто. И я должен сказать, что это очень полезный класс, у него внутри много методов, таких как сложение, вычитание, умножение, деление и другие методы операций, которые можно вызывать напрямую.
В дополнение к необходимости представлять числа с помощью BigDecimal и выполнять операции с числами, код часто требует суждений о равенстве для чисел.
Этот пункт знаний также объясняется в последней версии «Руководства по разработке Java для Alibaba»:
Какая мысль стоит за этим?
В предыдущих CodeReviews я видел ошибки низкого уровня, такие как следующие:
if(bigDecimal == bigDecimal1){
// 两个数相等
}
Такая ошибка, я считаю, что умный читатель может увидеть проблему с первого взгляда,Поскольку BigDecimal является объектом, его нельзя использовать.==
чтобы проверить, равны ли два числа.
Описанных выше проблем все же можно избежать после определенного опыта, но умные читатели, посмотрите на следующую строку кода, не думаете ли вы, что у него проблема:
if(bigDecimal.equals(bigDecimal1)){
// 两个数相等
}
Я могу четко сказать вам, что описанный выше способ написания может привести к результатам, отличным от ожидаемых!
В качестве эксперимента запустите следующий код:
BigDecimal bigDecimal = new BigDecimal(1);
BigDecimal bigDecimal1 = new BigDecimal(1);
System.out.println(bigDecimal.equals(bigDecimal1));
BigDecimal bigDecimal2 = new BigDecimal(1);
BigDecimal bigDecimal3 = new BigDecimal(1.0);
System.out.println(bigDecimal2.equals(bigDecimal3));
BigDecimal bigDecimal4 = new BigDecimal("1");
BigDecimal bigDecimal5 = new BigDecimal("1.0");
System.out.println(bigDecimal4.equals(bigDecimal5));
Вывод приведенного выше кода:
true
true
false
Принцип равенства BigDecimal
В приведенном выше примере кода мы обнаружили, что при использовании метода equals BigDecimal для сравнения 1 и 1.0 иногда это верно (при использовании int и double для определения BigDecimal), а иногда ложно (при использовании String для определения BigDecimal Time). ).
Итак, почему это происходит?Давайте сначала рассмотрим метод equals класса BigDecimal.
Причина уже объяснена в JavaDoc BigDecimal:
Compares this BigDecimal with the specified Object for equality. Unlike compareTo, this method considers two BigDecimal objects equal only if they are equal in value and scale (thus 2.0 is not equal to 2.00 when compared by this method)
Вероятно, это означает,Метод equals отличается от метода compareTo. Метод equals сравнивает две части: значение и масштаб.
Соответствующий код выглядит следующим образом:
Таким образом, точность двух объектов BigDecimal (bigDecimal4 и bigDecimal5), определенных приведенным выше кодом, различна, поэтому результат использования сравнения на равенство будет ложным.
Попробуйте отладить код, в процессе отладки мы также можем увидеть, что точность bigDecimal4 равна 0, а точность bigDecimal5 равна 1.
К этому моменту мы, вероятно, ясно объяснили, что причина, по которой equals сравнивает bigDecimal4 и bigDecimal5, ложна, потому что точность различна.
Так почему точность разная? Почему точность bigDecimal2 и bigDecimal3 одинакова (при использовании int, double для определения BigDecimal), но bigDecimal4 и bigDecimal5 не совпадают (при использовании String для определения BigDecimal)?
Почему точность отличается
Это связано с точностью BigDecimal. Эта проблема на самом деле более сложная. Поскольку это не является предметом этой статьи, я кратко представлю ее здесь. Если вам интересно, я расскажу об этом отдельно позже.
Прежде всего, у BigDecimal есть следующие 4 конструктора:
BigDecimal(int)
BigDecimal(double)
BigDecimal(long)
BigDecimal(String)
Точность BigDecimal, созданного четырьмя вышеуказанными методами, различна.
BigDecimal(long) и BigDecimal(int)
Во-первых, проще всегоBigDecimal(long) и BigDecimal(int), поскольку они являются целыми числами, точность равна 0.:
public BigDecimal(int val) {
this.intCompact = val;
this.scale = 0;
this.intVal = null;
}
public BigDecimal(long val) {
this.intCompact = val;
this.intVal = (val == INFLATED) ? INFLATED_BIGINT : null;
this.scale = 0;
}
BigDecimal(double)
А для BigDecimal(двойной),Когда мы используем new BigDecimal(0.1) для создания BigDecimal, созданное значение не точно равно 0,1, а 0,1000000000000000055511151231257827021181583404541015625. Это связано с тем, что сам доуль представляет собой лишь приближение.
Затем, независимо от того, используем ли мы новое определение BigDecimal(0.1) или новое определение BigDecimal(0.10), его приблизительное значение равно 0,1000000000000000055511151231257827021181583404541015625, тогда его точность равна количеству цифр этого числа, равному 55.
То же самое верно и для других чисел с плавающей запятой. Для формы new BigDecimal(1.0), поскольку она также является целым числом по своей природе, точность числа, которое она создает, равна 0.
Таким образом, поскольку точность BigDecimal(1.0) и BigDecimal(1.00) одинакова, при использовании метода equals для сравнения полученный результат является истинным.
BigDecimal(string)
А для BigDecimal(двойной),Когда мы используем new BigDecimal("0.1") для создания BigDecimal, созданное значение фактически равно 0,1. Тогда его точность равна 1.
Если вы используете new BigDecimal("0,10000"), то созданное число равно 0,10000, а точность равна 5.
Таким образом, поскольку точность BigDecimal("1,0") и BigDecimal("1,00") неодинакова, при использовании метода equals для сравнения полученный результат будет ложным.
Как сравнить BigDecimal
Ранее мы объясняли, что метод equals класса BigDecimal сравнивает не только значение числа, но и его точность.
Поэтому, когда мы используем метод равенства, чтобы определить, равны ли два числа, он чрезвычайно строг.
Итак, если мы хотим только судить, равны ли значения двух BigDecimals, как мы судим?
В BigDecimal предусмотрен метод compareTo, этот метод может сравнивать только значения двух чисел, если два числа равны, он вернет 0.
BigDecimal bigDecimal4 = new BigDecimal("1");
BigDecimal bigDecimal5 = new BigDecimal("1.0000");
System.out.println(bigDecimal4.compareTo(bigDecimal5));
Вывод приведенного выше кода:
0
Его исходный код выглядит следующим образом:
Суммировать
BigDecimal — очень полезный класс для представления высокоточных чисел, который предоставляет множество многофункциональных методов.
Однако его метод equals нужно использовать с осторожностью, потому что, когда он сравнивает, он не только сравнивает значение двух чисел, но и сравнивает их точность.Пока один из этих двух факторов не равен, результат также ложный .,
Если читатель хочет сравнить два значения BigDecimal, можно использовать метод compareTo.
Обратите внимание на официальный аккаунт: сцена интервью с программистом. Ответьте на «Руководство», чтобы получить последнюю версию руководства.