Bazaprogram.ru

Новости из мира ПК
4 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Java bigdecimal compareto

Особенности работы с java.math.BigDecimal

Если использовать типы double или float в Java, то можно заметить, что некоторые десятичные дроби не могут быть записаны в них без погрешности. Это связано с особенностью хранения данных в формате с плавающей точкой. Для того, чтобы увидеть эту погрешность, посмотрите вот этот пример:

В консоли будет написано далеко не 0.3.

В некоторых случаях такая погрешность может стать критической. Например, в случае когда мы считаем сумму всех денежных поступлений или списаний.

В Java существует специальный тип для точного хранения десятичных дробей с произвольным количеством знаков после запятой. Это java.math.BigDecimal. Предыдущий пример с использованием BigDecimal будет выглядеть так:

Теперь мы увидим ровно 0.3, как ожидалось.

Всегда используйте для хранения и обработки денежных сумм java.math.BigDecimal!

Советую также ознакомиться со статьей про числа в Java, где описаны и другие классы.

В java.math.BigDecimal есть другие полезные методы, кроме сложения:

BigDecimal abs() — возвращает абсолютное значение (убирает минус, если он есть).

BigDecimal add(BigDecimal augend) — сложение, которое использовалось в примере.

int compareTo(BigDecimal val) — сравнение. Возвращает 1, если текущее значение больше val, 0 если текущее значение равно val, -1 если текущее значение меньше val.

BigDecimal divide(BigDecimal divisor, int roundingMode) — деление. Количество знаков после запятой у возвращаемого значения this.scale().
BigDecimal divide(BigDecimal divisor, int scale, Rounding roundingMode) — деление. Возвращает BigDecimal, значение которого равно this/divisor, количество знаков после запятой равно scale.

BigDecimal multiply(BigDecimal multiplicand) — умножение. Возвращает результат умножения.

Это далеко не полный список методов. Все методы можно прочитать в официальной документации по ссылке в конце поста.

Обратите внимание, что некоторые методы принимают в качестве параметра RoundingMode. Это способ округления. Округление лучше всего ставить в RoundingMode.HALF_UP, потому что именно так и учат обычно округлять в школе. Старайтесь не использовать метод деления без параметра округления, так как он будет вызывать исключение в случае, когда результат невозможно точно представить в виде конечной десятичной дроби.

Также обратите внимание, что не стоит сравнивать BigDecimal с помощью equals. Используйте для этого метод compareTo, так как он корректно обрабатывает разную точность представления BigDecimal. Метод equals вернёт true только в том случае, если равны их значения и их точность. То есть для equals числа 2.0 и 2.00 не равны.

Особенности работы с java.math.BigDecimal: 2 комментария

Сразу же выполнил первый пример и увидел совсем не то, что ожидал: 0.3000000000000000166533453693773481063544750213623046875
Потом присмотрелся… оу, оказывается
System.out.println(new BigDecimal(0.1));
и
System.out.println(new BigDecimal(«0.1»));
дают разный результат.
Последний момент про equals тоже интересный.

Спасибо за статью

Спасибо. Полезная информация и доступно изложена.

Java BigDecimal

Java BigDecimal class is used to deal with financial data. BigDecimal is preferred while dealing with high-precision arithmetic or situations that require more granular control over rounding off calculations.

Table of Contents

Java BigDecimal

BigDecimals are Immutable, arbitrary-precision signed decimal numbers. Java BigDecimal class is defined in java.math package. Here is the BigDecimal class hierarchy:

Java BigDecimal also provides us convenient control over scale and precision. Before we explore BigDecimal class, we’ll briefly discuss precision and scale.

Java BigDecimal Precision and Scale

By Definition, precision indicates the length of arbitrary precision integer whereas scale means the number of digits to the right of the decimal point. For example if we have a number “100.25” then precision is 5 because we need five digits to write down this number and scale is 2.

We’ll look at some examples to get the clear idea about precision and scale.

We can set scale for any BigInteger with constructors as well as methods available in the API. For now, let’s see how it effects the number:

Читать еще:  Java kafka consumer

We can clearly see that number gets multiplied by 10^-scale .

Java BigDecimal Constructors

There are several ways to create BigDecimal objects in Java. We’ll explore the constructors with code examples.

    BigDecimal(BigInteger val) : It takes BigInteger as an argument and creates a BigDecimal Object out of it.

Similarly, there are constructors available in the class which accept int, double, long, char[] as well as String as an argument to create BigDecimal object:

BigDecimal(BigInteger unscaledVal, int scale) : We can also provide scale along with the value while creating the object.

BigDecimal(BigInteger val, MathContext mc) : It also gives us control to provide MathContext instance while creating the object.
Basically, it provides precision matching IEEE 754R Format. Following are the possible values for java.math.MathContext :

  1. MathContext.DECIMAL128 ? to provide precision of 34 digits.
  2. MathContext.DECIMAL64 – to provide precision of 16 digits.
  3. MathContext.DECIMAL32 ? to provide precision of 7 digits.
  4. MathContext.UNLIMITED ? to provide unlimited precision.

Let’s look at the code:

Ofcourse, it also provides similar constructors for int, long, double, char[] as well as String.
BigDecimal(BigInteger unscaledVal, int scale, MathContext mc) : we can provide both scale and precision at the time of construction of an object.

Java BigDecimal Methods

Java BigDecimal class provides us with several method to perform arithmatic operations, scale manipulation, rounding, comparision and formatting.

Note that we can’t use operators such as +, – with it as they are not overloaded for the class. Instead, it provides respective methods to achieve the results.
Let’s look at the methods provided in the BigDecimal API with examples:

    BigDecimal add(BigDecimal bigDecimal2) : Returns a BigDecimal whose value is addition of this and bigDecimal2 .

As you can see, returned object from add() method has scale which is max(this.scale, bigDecimal2). In our case, bigDecimal2 is created with the double and takes the scale value from it.
There is also an overloaded add(BigDecimal bigDecimal2, MathContext mc) method which takes precision as argument and returns a BigDecimal object with rounding according to context settings.
BigDecimal subtract(BigDecimal bigDecimal2) : Returns a BigDecimal whose value is subtraction of this and bigDecimal2 .
Similar to add() method, it also has privision to provide MathContext instance.

BigDecimal setScale(int newScale, RoundingMode roundingMode) : A very Convinient and powerful method which allows us to set scale as well as rounding mode of the object. We already discussed scale. Let’s briefly discuss rounding mode and its possible values:
An enum RoundingMode provides following possible rounding:

  1. UP: to round away from zero
  2. CEILING: to round towards positive infinity
  3. DOWN: to round towards zero
  4. FLOOR: to round towards negative infinity
  5. HALF_DOWN: to round towards “nearest neighbor” unless both neighbors are equidistant, in which case round down
  6. HALF_EVEN: to round towards the “nearest neighbor” unless both neighbors are equidistant, in which case, round towards the even neighbor
  7. HALF_UP: to round towards “nearest neighbor” unless both neighbors are equidistant, in which case round up
  8. UNNECESSARY: to assert that the requested operation has an exact result, hence no rounding is necessary

BigInteger unscaledValue() : We can also get unscaled values at any point of time.
For Example, following code:

there is also scale() method which returns scale of the BigDecimal object

  • BigDecimal divide(BigDecimal divisor, int roundingMode) : Computes division of this and divisor and returns the output with provided roundingMode.
  • BigDecimal divide(BigDecimal divisor, int scale, int roundingMode) : Computes division of this and divisor and returns the output with provided roundingMode and scale.
  • BigDecimal multiply(BigDecimal multiplicand) : Computes multiplication of this and multiplicand and returns the output.
  • BigDecimal pow(int n) : Returns a BigDecimal whose value is (this^n), The power is computed exactly, to unlimited precision.
  • Читать еще:  Arithmetic exception java

    Note that for each operator method, there is an overloaded method which accepts MathContext object and returns the output with respective precision.

    Java BigDecimal Example

    Now, let’s have a look at an example to check out above java BigDecimal methods:

    There are many methods provided in the BigDecimal class for various operators such as min() , max() . Also, it provides with methods such as intValue() , doubleValue() , longValue() to get output in required format.

    Java BigDecimal Formatting

    We can use the api along with java.text.NumberFormat to apply desired formatting to the big numbers. For instance, let’s say we want to print the amount in USD:

    Java BigDecimal compareTo

    Java BigDecimal class implements Comparable interface and we should use it’s compareTo method to compare two BigDecimal objects.

    Note that two BigDecimal objects that are equal in value but have a different scale (like 10.0 and 10.00) are considered equal by compareTo method.

    Output of above BigDecimal compareTo example code is:

    Java BigDecimal toString

    Java BigDecimal toString method behaves differently based on the scale value. If the scale is 6 or more, then it prints in exponential notation. Below are some pseudo code to show the BigDecimal value with scale and the String representation returned by toString method.

    Here is a simple java example for BigDecimal toString example.

    Output produced by above BigDecimal toString example code is:

    BigDecimal and BigInteger in Java

    Last modified: July 20, 2019

    I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

    In the 9 years of running Baeldung, I’ve never, ever done a «sale».
    But. we’ve also not been through anything like this pandemic either.
    And, if making my courses more affordable for a while is going to help a company stay in business, or a developer land a new job, make rent or be able to provide for their family — then it’s well worth doing.
    Effective immediately, all Baeldung courses are 33% off their normal prices!
    You’ll find all three courses in the menu, above, or here.

    1. Overview

    In this tutorial, we will demonstrate BigDecimal and the BigInteger classes.

    We’ll describe the two data types, their characteristics, and their usage scenarios. We’ll also briefly cover the various operations using the two classes.

    2. BigDecimal

    BigDecimal represents an immutable arbitrary-precision signed decimal number. It consists of two parts:

    • Unscaled value – an arbitrary precision integer
    • Scale – a 32-bit integer representing the number of digits to the right of the decimal point

    For example, the BigDecimal 3.14 has the unscaled value of 314 and the scale of 2.

    We use BigDecimal for high-precision arithmetic. We also use it for calculations requiring control over scale and rounding off behavior. One such example is calculations involving financial transactions.

    We can create a BigDecimal object from String, character array, int, long, and BigInteger:

    We can also create BigDecimal from double:

    However, the result, in this case, is different from expected (that is 0.1). This is because:

    • the double constructor does an exact translation
    • 0.1 does not have an exact representation in double

    Therefore, we should use the String constructor instead of the double constructor.

    In addition, we can convert double and long to BigInteger using the valueOf static method:

    This method converts double to its String representation before converting to BigDecimal. In addition, it may reuse object instances.

    Hence, we should use the valueOf method in preference to the constructors.

    Читать еще:  Java nio charset malformedinputexception

    3. Operations on BigDecimal

    Just like the other Number classes (Integer, Long, Double etc.), BigDecimal provides operations for arithmetic and comparison operations. It also provides operations for scale manipulation, rounding and format conversion.

    It does not overload the the arithmetic (+, -, /, *) or logical (>.

    There are two classes which control rounding behavior – RoundingMode and MathContext.

    The enum RoundingMode provides eight rounding modes:

    • CEILING – rounds towards positive infinity
    • FLOOR – rounds towards negative infinity
    • UP – rounds away from zero
    • DOWN – rounds towards zero
    • HALF_UP – rounds towards “nearest neighbor” unless both neighbors are equidistant, in which case rounds up
    • HALF_DOWN – rounds towards “nearest neighbor” unless both neighbors are equidistant, in which case rounds down
    • HALF_EVEN – rounds towards the “nearest neighbor” unless both neighbors are equidistant, in which case, rounds towards the even neighbor
    • UNNECESSARY – no rounding is necessary and ArithmeticException is thrown if no exact result is possible

    HALF_EVEN rounding mode minimizes the bias due to rounding operations. It is frequently used. It is also known as the banker’s rounding.

    MathContext encapsulates both precision and rounding mode. There are few predefined MathContexts:

    • DECIMAL32 – 7 digits precision and a rounding mode of HALF_EVEN
    • DECIMAL64 – 16 digits precision and a rounding mode of HALF_EVEN
    • DECIMAL128 – 34 digits precision and a rounding mode of HALF_EVEN
    • UNLIMITED – unlimited precision arithmetic

    Using this class, we can round a BigDecimal number using specified precision and rounding behavior:

    Now, let’s examine the rounding concept using a sample calculation.

    Let’s write a method to calculate the total amount to be paid for an item given a quantity and unit price. Let’s also apply a discount rate and sales tax rate. We round the final result to cents by using the setScale method:

    Now, let’s write a unit test for this method:

    5. BigInteger

    BigInteger represents immutable arbitrary-precision integers. It is similar to the primitive integer types but allows arbitrary large values.

    It is used when integers involved are larger than the limit of long type. For example, the factorial of 50 is 30414093201713378043612608166064768844377641568960512000000000000. This value is too big for an int or long data type to handle. It can only be stored in a BigInteger variable.

    It is widely used in security and cryptography applications.

    We can create BigInteger from a byte array or String:

    In addition, we can convert a long to BigInteger using the static method valueOf:

    6. Operations on BigInteger

    Similar to int and long, BigInteger implements all the arithmetic and logical operations. But, it does not overload the operators.

    It also implements the corresponding methods from Math class: abs, min, max, pow, signum.

    We compare the value of two BigIntegers using the compareTo method:

    We perform arithmetic operations by calling the corresponding methods:

    As BigInteger is immutable, these operations do not modify the existing objects. Unlike, int and long, these operations do not overflow.

    BigInteger has the bit operations similar to int and long. But, we need to use the methods instead of operators:

    It has additional bit manipulation methods:

    BigInteger provides methods for GCD computation and modular arithmetic:

    It also has methods related to prime generation and primality testing:

    7. Conclusion

    In this quick tutorial, we explored the classes BigDecimal and BigInteger. They are useful for advanced numerical computations where the primitive integer types do not suffice.

    As usual, the full source code can be found over on GitHub.

    Ссылка на основную публикацию
    Adblock
    detector