Класс java math и его методы

Суть проблемы

Когда мы начали создавать сервисы General Ledger для бухгалтерского учета, то обнаружили, что во многих местах были ошибки в 0.01 или более процентов. Это делает учёт денег практически невозможным. Кто хотел бы выставить счёт клиенту на $4.01, когда в его заказе $4.00?

Причины этих ошибок стали понятны достаточно быстро: расчёты, которые содержат суммы, количества, коррективы, и многие другие вещи обычно выполняются с малым или вообще без внимания к особенностям проблем точности и округления, которые возникают при работе с финансами.

Все эти вычисления использовали тип Java double, который не предлагает способа управления округлением числа или ограничения точности в расчётах. Мы пришли к решению, включающему использование java.math.BigDecimal, что дает нам управлять всем этим.

Эта статья — пример проблем математики финансов и учебник по использованию BigDecimal в целом.

parseInt и parseFloat

Для явного преобразования к числу можно использовать или . Если строка не является в точности числом, то результат будет :

Единственное исключение — это пробелы в начале строки и в конце, они игнорируются.

В реальной жизни мы часто сталкиваемся со значениями у которых есть единица измерения, например или в CSS. Также во множестве стран символ валюты записывается после номинала . Так как нам получить числовое значение из таких строк?

Для этого есть и .

Они «читают» число из строки. Если в процессе чтения возникает ошибка, они возвращают полученное до ошибки число. Функция возвращает целое число, а возвращает число с плавающей точкой:

Функции вернут , если не смогли прочитать ни одну цифру:

Второй аргумент

Функция имеет необязательный второй параметр. Он определяет систему счисления, таким образом может также читать строки с шестнадцатеричными числами, двоичными числами и т.д.:

Rounding Doubles With BigDecimal

To round doubles to n decimal places, we can write a helper method:

There is one important thing to notice in this solution – when constructing BigDecimal; we must always use BigDecimal(String) constructor. This prevents issues with representing inexact values.

We can achieve the same by using the Apache Commons Math library:

The latest version can be found .

Once the library is added to the project, we can use the Precision.round() method, which takes two arguments – value and scale:

By default, it is using the same HALF_UP rounding method as our helper method. Therefore, the results should be the same.

Note that we can change rounding behavior by passing the desired rounding method as a third parameter.

Java Math.round on Array example

In this Java program, we find the rounded values of bulk data. Here, we are going to declare an array of double type and find the closest (rounded) values of array elements using java math.round.

OUTPUT

ANALYSIS

Within this Java round example, we declared an Array of double type and assigned some random values.

Next, We used the Java For Loop to iterate the Array. Within the For Loop, we initialized the i value as 0.

Next, compiler will check for the condition (i < myArray.length). As along the condition is True statement inside the for loop executed.

TIP: myArray.length finds the length of the Java array.

The following statements will print the output. If you observe the code snippet, we used the round Function directly inside System.out.format statement.

Here, the compiler will call the Java Math.round method ( static long round(double number) ) to find the corresponding closet (rounded) values.

NOTE: To find the closet (rounded) value of a single item, then use: Math.round(myArray)

Приоритет оператора Java Math

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

Математические операторы * и / для умножения и деления имеют приоритет над операторами + и -. Это означает, что умножения и деления вычисляются перед сложением и вычитанием в математических выражениях. В случае наличия нескольких операторов * и / они будут рассчитаны слева направо. Посмотрите на это математическое выражение:

int result = 100 * 100 / 5 + 200 * 3 / 2;

Сначала выполняются умножения и деления. Есть две группы из трех умножений и делений. Каждая группа выполняется слева направо:

100 * 100 = 10000;
10000 / 5 = 2000;
200 * 3 = 600;
600 / 2 = 300;

После вычисления умножения и деления математическое выражение выглядит так:

int result = 2000 + 600;

Теперь сложения и вычитания выполняются. Таким образом, значение, присвоенное переменной результата, равно 2000 + 600 = 2600.

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

int result = 100 * 100 /(5 + 200) * 3 / 2;

Значение 100 все еще умножается на 100 (= 10 000), но теперь оно делится на 5 + 200 (= 205) вместо 5. После этого деления результат умножается на 3, а затем делится на 2. Результат выполнения 72 (округление вычислений влияет на результат).

Java Integer Math

Математические операции, выполняемые с целочисленными типами Java (byte, short, int и long), ведут себя немного иначе, чем обычные математические операции. Поскольку целочисленные типы не могут содержать дроби, в каждом вычислении с одним или несколькими целочисленными типами все дроби в результате обрезаются. Посмотрите на это математическое выражение:

int result = 100 / 8;

Результат этого деления будет 12,5, но так как два числа являются целыми числами, фракция .5 обрезается. Результат, следовательно, всего 12.

Округление также происходит в подрезультатах больших вычислений.

С плавающей точкой Math

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

double result = 100 / 8;

Несмотря на то, что переменная результата теперь имеет тип с плавающей запятой (double), конечный результат по-прежнему равен 12 вместо 12,5. Причина в том, что оба значения в математическом выражении (100 и 8) оба являются целыми числами. Таким образом, результат деления одного на другое сначала преобразуется в целое число (12), а затем присваивается переменной результата.

Чтобы избежать округления вычислений, необходимо убедиться, что все типы данных, включенные в математическое выражение, являются типами с плавающей запятой. Например, вы могли бы сначала присвоить значения переменным с плавающей запятой следующим образом:

double no1 = 100;
double no2 = 8;

double result = no1 / no2;

Теперь переменная результата будет иметь значение 12,5.

В Java есть способ заставить все числа в расчете быть переменными с плавающей точкой. Вы ставите числа с большой буквы F или D. Вот пример:

double result = 100D / 8D;

Обратите внимание на прописные буквы D после каждого числа. Этот верхний регистр D говорит Java, что эти числа должны интерпретироваться как числа с плавающей запятой, и, таким образом, деление должно быть делением с плавающей запятой, которое сохраняет дроби вместо их обрезания

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

Точность с плавающей точкой

Типы данных с плавающей точкой не являются точными на 100%. Вы можете столкнуться с ситуациями, когда числа со многими дробями не складываются с ожидаемым числом. Если вычисление с плавающей запятой приводит к числу с большим количеством дробей, чем может обработать число с плавающей запятой или двойное число, дроби могут быть обрезаны. Конечно, заданная точность может быть более чем достаточной для многих типов вычислений, но имейте в виду, что дроби могут фактически быть отсечены.

Посмотрите:

double resultDbl3 = 0D;
System.out.println("resultDbl3 = " + resultDbl3);

for(int i=0; i<100; i++){
    resultDbl3 += 0.01D;
}
System.out.println("resultDbl3 = " + resultDbl3);

Вывод выводится при выполнении этого кода с Java 8:

resultDbl3 = 0.0
resultDbl3 = 1.0000000000000007

Первый оператор System.out.println() правильно печатает значение 0.0, которое является начальным значением переменной resultDbl3.

Однако второй оператор System.out.println() выводит несколько странный результат. Добавление значения 0,01 к 0 всего 100 раз должно привести к значению 1,0, верно? Но каким-то образом окончательный результат 1.0000000000000007. Как видите, что-то не так во фракциях.

Обычно неточность с плавающей запятой незначительна, но все же важно знать об этом

Математические вычисления и класс Math

Последнее обновление: 28.10.2018

Для выполнения различных математических операций в Java в пакете java.lang определен класс
Math. Рассмотрим его основные методы:

  • : возвращает абсолютное значение для аргумента value

    double result = Math.abs(-13.5); // 13.5
    
  • : возвращает арккосинус value. Параметр value должен иметь значение от -1 до 1

    double result = Math.acos(1); // 0.0
    
  • : возвращает арксинус value. Параметр value должен иметь значение от -1 до 1

  • : возвращает арктангенс value

  • : возвращает кубический корень числа value

    double result = Math.cbrt(27); // 3
    
  • : возвращает наименьшее целое число с плавающей точкой, которое не меньше value

    double result = Math.ceil(2.34); // 3
    
  • : возвращает косинус угла d

  • : возвращает гиперболический косинус угла d

  • : возвращает основание натурального логарифма, возведенное в степень d

  • : возвращает наибольшее целое число, которое не больше d

    double result = Math.floor(2.56); // 2
    
  • : возвращает целочисленный результат деления a на b

    System.out.println(Math.floorDiv(1, 2)); // 0
    System.out.println(Math.floorDiv(7, 2)); // 3
    System.out.println(Math.floorDiv(9, 2)); // 4
    
  • : возвращает натуральный логарифм числа a

  • : возвращает натуральный логарифм числа (d + 1)

  • : возвращает десятичный логарифм числа d

  • : возвращает максимальное число из a и b

  • : возвращает минимальное число из a и b

  • : возвращает число a, возведенное в степень b

  • : возвращает случайное число от 0.0 до 1.0

  • : возвращает число double, которое представляет ближайшее к числу value целое число

    System.out.println(Math.rint(2)); // 2.0
    System.out.println(Math.rint(2.3)); // 2.0
    System.out.println(Math.rint(2.5)); // 2.0
    System.out.println(Math.rint(2.5001)); // 3.0
    System.out.println(Math.rint(2.8)); // 3.0
    
  • : возвращает число d, округленное до ближайшего целого числа

    System.out.println(Math.round(2.3)); // 2
    System.out.println(Math.round(2.5)); // 3
    System.out.println(Math.round(2.5001)); // 3
    System.out.println(Math.round(2.8)); // 3
    
  • : возвращает произведение числа value на 2 в степени factor

    System.out.println(Math.scalb(5, 3)); // 5*2*2*2 = 40
    System.out.println(Math.scalb(3, 4)); // 3*2*2*2*2 = 48
    
  • : возвращает число 1, если число value положительное, и -1, если значение value отрицательное. Если value равно 0, то возвращает 0

    System.out.println(Math.signum(2.3)); // 1
    System.out.println(Math.signum(-2.3)); // -1
    
  • : возвращает синус угла value

  • : возвращает гиперболический синус угла value

  • : возвращает квадратный корень числа value

    double result1 = Math.sqrt(16); // 4
    
  • : возвращает тангенс угла value

  • : возвращает гиперболический тангенс угла value

  • переводит радианы в градусы и — градусы в радианы

    System.out.println(Math.toDegrees(3.14159)); // 180
    System.out.println(Math.toRadians(90)); // 1,57079....
    

Также класс Math определяет две константы: и . Например, вычислим площадь круга:

import java.util.Scanner;

public class Program {
  
    public static void main(String[] args) {
          
        Scanner in = new Scanner(System.in);
        
        System.out.print("Введите радиус круга: ");
        int radius = in.nextInt();
        long area = Math.round(Math.PI * Math.pow(radius, 2));
        System.out.printf("Площадь круга с радиусом %d равна %d \n", radius, area);
    }
}

Консольный вывод:

Введите радиус круга: 10
Площадь круга с радиусом 10 равна 314

НазадВперед

What does rounding mean?

Rounding is the mathematical process of making the number up or down to the nearest whole number. In this number process, any given decimal number is converted to the nearest whole number. For example,

  1. 3.2 is rounded to 3
  2. 3.7 is rounded to 4
  3. 3.5 is rounded to 4
  4. 7.49 is rounded to 7
  5. 7.4999999 is rounded to 7

Note: When the first digit after the decimal point is less than 5, then the number is rounded to lower integer and when it is 5 or more, then it is rounded to the next integer. Another important thing to remember is, not to double round. Do not round 7.49 as 7.5 and then round 7.5 to 8. Remember that, 7.49 is always rounded to 7.

Java Math.Round()

Oct 30, 2017 Java, Java Math comments

Math.Round Examples

Round Float Values

public static int round(float a)
float num1 = 14.4f;
float num2 = 14.6f;
int roundedNum1 = Math.round(num1);
int roundedNum2 = Math.round(num2);
System.out.println(roundedNum1);
System.out.println(roundedNum2);
14
15

If we make it negative values, for example:

float num1 = -14.4f;
float num2 = -14.6f;
int roundedNum1 = Math.round(num1);
int roundedNum2 = Math.round(num2);
System.out.println(roundedNum1);
System.out.println(roundedNum2);
-14
-15
  • If the argument is NaN, the result is 0. — since a float number can have the value Nan, the converted value will be 0 for such case. Example, consider this code:

    float num = Float.NaN;
    System.out.println(num);
    int roundedNum = Math.round(num);
    System.out.println(roundedNum);
    

    Will have this output:

    NaN
    0
    
  • If the argument is negative infinity or any value less than or equal to the value of Integer.MIN_VALUE, the result is equal to the value of Integer.MIN_VALUE. — The value of Integer.MIN_VALUE is -2147483648, which is the lowest value that this method can return. Example:

    float num = -1/0.0f;
    int roundedNum = Math.round(num);
    System.out.println(num);
    System.out.println(roundedNum);
    

    We produce a negative infinity number by dividing a negative number by 0. The rounded value of that is the Integer.MIN_VALUE. The output of the code therefore will be:

    -Infinity
    -2147483648
    
  • If the argument is positive infinity or any value greater than or equal to the value of Integer.MAX_VALUE, the result is equal to the value of Integer.MAX_VALUE. — The value of Integer.MAX_VALUE is 2147483647, which is the biggest value that this method can return.

    float num = 1/0.0f;
    int roundedNum = Math.round(num);
    System.out.println(num);
    System.out.println(roundedNum);
    

    We produce infinity number by dividing a positive number by 0. The rounded value of that is the Integer.MAX_VALUE. The output of the code above will be:

    Infinity
    2147483647
    

Round Double Values

public static long round(double a)
double num1 = 52147483647.4d;
double num2 = 52147483647.6d;
long roundedNum1 = Math.round(num1);
long roundedNum2 = Math.round(num2);
System.out.println(roundedNum1);
System.out.println(roundedNum2);
52147483647
52147483648

If we make it negative values, for example:

double num1 = -52147483647.4d;
double num2 = -52147483647.6d;
long roundedNum1 = Math.round(num1);
long roundedNum2 = Math.round(num2);
System.out.println(roundedNum1);
System.out.println(roundedNum2);
-52147483647
-52147483648

Edge cases are also similar:

  • If the argument is NaN, the result is 0. — The behavior is similar as described above, example code:

    double num = Double.NaN;
    long roundedNum = Math.round(num);
    System.out.println(num);
    System.out.println(roundedNum);
    

    the output is:

    NaN
    0
    

If the argument is negative infinity or any value less than or equal to the value of Long.MIN_VALUE, the result is equal to the value of Long.MIN_VALUE. — Similarly, the lowest value that this method will return is Long.MIN_VALUE or -9223372036854775808. See this code sample:

double num = Double.NEGATIVE_INFINITY;
long roundedNum = Math.round(num);
System.out.println(num);
System.out.println(roundedNum);

the output is:

-Infinity
-9223372036854775808

If the argument is positive infinity or any value greater than or equal to the value of Long.MAX_VALUE, the result is equal to the value of Long.MAX_VALUE. — And as expected, the highest value that this method will return is Long.MAX_VALUE or 9223372036854775807. See this code sample:

double num = Double.POSITIVE_INFINITY;
long roundedNum = Math.round(num);
System.out.println(num);
System.out.println(roundedNum);

the output is:

Infinity
9223372036854775807

Класс Java Math

Класс Java Math предоставляет более сложные математические вычисления, чем те, которые предоставляют базовые математические операторы Java. Класс Math содержит методы для:

  • нахождения максимального или минимального значений;
  • значений округления;
  • логарифмических функций;
  • квадратного корня;
  • тригонометрических функций (sin, cos, tan и т. д.).

Math находится в пакете java.lang, а не в пакете java.math. Таким образом, полное имя класса Math — это java.lang.Math.

Поскольку многие его функции независимы друг от друга, каждый метод будет объяснен в своем собственном разделе ниже.

Java Math.round Syntax

The basic syntax of the round Function in Java Programming language is as shown below.

Number: It can be a number or a valid numerical expression.

  • If the number argument is a positive or negative number, the Math.round function will return the nearest value.
  • If the number argument is not a number, the Java Math.round function will return Zero.

Java Programming provides two different functions to round the specified value. The following Java math.round function will accept positive or negative float value as an argument and returns the closest mathematical integer value of type Int.

The following Java round double function will accept the positive or negative double value and returns the closest math integer value of type long.

4 Минимум и максимум из нескольких чисел

Есть еще одно полезное применение функций и .

Это вычисление минимума (или максимума) из нескольких чисел или переменных. Функции очень удобно вызывать друг в друге.

Вот как можно записать минимум из 3-х чисел:

А что? Очень удобно: вычисляем минимум пары чисел, а затем возвращаем меньшее число из найденного и оставшегося.

Минимум из четырех чисел получается аналогично:

Хотя можно эту формулу записать немного понятнее:

Для функции все аналогично.

Использование оператора или тернарного оператора сделало бы эти записи немного более громоздкими. А использование функций и — просто идеальное решение.

2 Алгебраические функции в Java

В большинстве случаев программисту с головой хватает школьной математики: даже синусы и косинусы в коде можно встретить очень редко. Чаще всего они нужны при работе с играми, картами или игровыми движками. 90% программистов с этим никогда не сталкиваются.

Но, кроме геометрии, программистам иногда приходится использовать и алгебраические функции. И, конечно же, класс содержит самые распространенные из них:

Метод Описание
квадратный корень из
кубический корень из
возведение в степень:
экспонента:
натуральный логарифм :
десятичный логарифм :
натуральный логарифм :

Если вам нужен квадратный или кубический корень из числа, для этого есть функции и .

Корень из двух можно вычислить так:

Если вы хотите получить корень более высокой степени, воспользуйтесь функцией возведения в степень: в степени — это и будет корень четвертой степени, и т.д.

Для работы с логарифмами и экспонентами есть функции – натуральный логарифм и — экспонента. Для вычисления десятичного логарифма есть функция .

Если вам нужен логарифм числа по основанию , воспользуйтесь простой формулой:

Полезные функции

Последние две функции и могут быть вам полезны, если вы проводите вычисления при очень маленьких значениях .

При сложении очень маленьких и очень больших переменных часто может возникнуть ситуация, когда очень маленькое значение просто игнорируется (отбрасывается) как незначащее. Это, собственно, и будет происходить, если использовать функции и . Поэтому программисты придумали функции, которые возвращают только ту самую «маленькую значащую часть»

Пример:

Вы хотите посчитать натуральный логарифм от , где равен . Вы просто не сможете передать это число в функцию , т.к. если сложить и , получится . — настолько маленькое число, что будет отброшено полностью при сложении чисел.

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

Пример проблем при учёте финансов

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

Например, предположим, что у нас есть продукт, который стоит 10.00 в заданной валюте и местный налог с продаж 0.0825, или 8.25%. Если посчитать налог на бумаге, сумма будет:

10.00 * 0.0825 = 0.825

Поскольку точность расчёта для данной валюты две цифры после запятой, требуется округлить число 0.825. Кроме того, поскольку это налог, обычной практикой является постоянное округление до цента в большую сторону. Таким образом, после расчёта баланса по счетам в конце дня мы никогда не получим недоплату налогов.

0.825 -> 0.83

И таким образом клиенту выставляется общий счёт на сумму 10.83 в местной валюте, а сборщику налогов выплачивается 0.83

Обратите внимание, что если продать 1000 таких продуктов, то переплата сборщику налогов была бы:. 1000 * (0.83 — 0.825) = 5.00

1000 * (0.83 — 0.825) = 5.00

100.0 * 0.528361 = 52.8361

Так как это не налог, можно округлить эту цифру вверх или вниз на своё усмотрение. Предположим, округление выполняется в соответствии со стандартными правилами округления: если следующая значащая цифра меньше 5, округляем в меньшую сторону. В противном случае округляем вверх. Это даёт для окончательной цены значение 52.84.

Теперь предположим, что мы хотим дать рекламную скидку в размере 5% от всей покупки. Делать скидку с цифры 52.8361 или 52.84? Какова разница?

Расчёт 1: 52.8361 * 0.95 = 50.194295 = 50.19

Расчёт 2: 52.84 * 0.95 = 50.198 = 50.20

Обратите внимание, что окончательная цифра округлена по стандартному правилу округления. Видите разницу в один цент между двумя цифрами? Старый код не беспокоился о принятии во внимание округления, поэтому он всегда делал вычисления как в Расчёте 1

Но в новом коде перед расчётом скидок, налогов и всего другого сначала выполняется округление, как и в Расчёте 2. Это одна из главных причин для ошибки в один цент

Видите разницу в один цент между двумя цифрами? Старый код не беспокоился о принятии во внимание округления, поэтому он всегда делал вычисления как в Расчёте 1. Но в новом коде перед расчётом скидок, налогов и всего другого сначала выполняется округление, как и в Расчёте 2

Это одна из главных причин для ошибки в один цент.

Итого

Чтобы писать числа с большим количеством нулей:

  • Используйте краткую форму записи чисел – , с указанным количеством нулей. Например: это с 6-ю нулями .
  • Отрицательное число после приводит к делению числа на 1 с указанным количеством нулей. Например: это ( миллионных).

Для других систем счисления:

  • Можно записывать числа сразу в шестнадцатеричной (), восьмеричной () и бинарной () системах счисления
  • преобразует строку в целое число в соответствии с указанной системой счисления: .
  • представляет число в строковом виде в указанной системе счисления .

Для преобразования значений типа и в число:

Используйте parseInt/parseFloat для «мягкого» преобразования строки в число, данные функции по порядку считывают число из строки до тех пор пока не возникнет ошибка.

Для дробей:

  • Используйте округления , , , или .
  • Помните, что при работе с дробями происходит потеря точности.

Ещё больше математических функций:

Документация по объекту Math

Библиотека маленькая, но содержит всё самое важное

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Adblock
detector