Русские Блоги
Целочисленное деление, остаток и округление в Java и Python
Что касается разделения, вы можете подумать, что здесь не о чем говорить, ведь учитель физкультуры учил нас в начальной школе. Однако я думаю, что в отношении разделения, используемого в программировании, есть еще много примечательных деталей. Почему я хочу копать глубже? Поскольку я в основном использую Java и Python для программирования каждый день, и их подразделения имеют много различий в деталях, они все ямы . Так что я также сосредоточусь на Java и Python, но поверьте мне, даже если вы не используете Java и Python, будут выгоды.
1. Целочисленное деление
Разделите два целых числа, которые не делятся, и вам придется столкнуться с проблемами округления. Как и в большинстве языков программирования, основная стратегия Java — округлять до нуля, то есть до меньшего абсолютного значения. Дайте несколько сладких каштанов: 3/2 = 1, -3 / 2 = -1. Для Python ситуация иная.
>>>-1/10 -1``` Очевидно, что если вы следуете стратегии округления Java, -1/10 должно быть 0, а Python дает результат -1. Фактически, метод округления Python округляет в меньшую сторону, то есть округляет числовую строку в сторону отрицательной бесконечности. Ну, у Java и Python разные методы округления, что очень важно . Тогда, если мы хотим использовать результат округления до нуля в Python, как округлить? Более простой способ: ```python >>>int(float(-1)/10) 0``` ## 2. Возьмите остаток Кто сказал, что это нормально? (╰ ( ̄ ▽  ̄) ╭) Грядет большое дело! Целочисленное деление как в Java, так и в Python следует этой формуле: >(a/b)*b+c=a Другими словами: >a mod b=c=a-(a/b)*b Здесь / означает целочисленное деление. Поскольку их методы округления различны, остальная часть также будет затронута: >For Java: -2 % 3==-2 For Python: -2 % 3==1 В некоторых практических приложениях нам может потребоваться получить целое число цифр. Если входное целое число положительно, и Java, и Python могут использовать один и тот же метод для решения: ```python def func(a): pos, res=1, [] while a/pos: res+=(a/pos)%10, pos*=10 return res``` Код Java почти такой. Но если входное целое число является отрицательным числом, версия кода для Java все равно может получить правильный результат, а Python - нет (здесь он был разбит, поднимите руку). Как использовать Python для правильного решения этой проблемы? Вы можете сначала перейти к абсолютному значению и знаку, рассматривать его как положительное число и, наконец, добавить знак в результат. ##3. Follow-ups ### 3.1 Другая операция деления в Python Мы знаем, что в Python основной знак деления «/» перегружен. Если оба операнда являются целыми числами, выполните целочисленное деление, чтобы получить целочисленный результат, в противном случае выполните деление с плавающей запятой (истинное деление), чтобы получить результат с плавающей запятой. Начиная с Python 2.2, был введен другой знак деления: //, который выполняет только целочисленное деление. Обратите внимание, что тип результата // зависит от операнда. ```python >>>1.0/2 0.0 >>>1.0//2.0 0.0 >>>1//2 >0``` Кроме того, если вы хотите получить частное и остаток одновременно, вы можете использовать встроенную функцию divmod, и результатом будет кортеж. ```python >>>divmod(7, 2) (3, 1) >>>divmod(7.0, 2) (3.0, 1.0)``` ### 3.2 Округление в Python В дополнение к методу округления по умолчанию, Python имеет множество вариантов округления. **Floor rounding:** ```python >>>import math >>>math.floor(1.2) 1.0 >>>math.floor(-1.2) -2.0``` **Ceiling rounding:** ```python >>>math.ceil(1.2) 2.0 >>>math.ceil(-1.2) -1.0``` **Round-off:** ```python >>>round(0.5) 1.0 >>>round(-0.4) -0.0 >>>round(-0.5) -1.0``` Встроенная функция округления также может иметь параметр, указывающий количество десятичных знаков: ```python >>>round(0.21, 1) 0.2 >>>round(0.21, 2) 0.21``` **Caution !** ```python >>>round(2.675, 2) 2.67
Хм? ошибка? ! конечно, нет. Здесь необходимо прояснить одно: компьютеры распознают только 0 и 1 (квантовый компьютер? Невежественный). Другими словами, все вводимые десятичные числа выражаются в компьютере в двоичном формате. Некоторые десятичные числа могут быть точно представлены в двоичном формате. Например, 0,125 в десятичной системе может быть представлено как 0b0.001; однако многие десятичные числа не могут быть точно представлены в двоичной системе. Компьютер сохраняет их приблизительные значения, например 0,1 в десятичной системе., В двоичном формате может быть приблизительно выражено как: 0b0.00011001100110011001100110011001100110011001100110011010 , Поэтому, когда мы преобразуем его обратно в десятичное число для вывода или использования, полученное значение будет 0.1000000000000000055511151231257827021181583404541015625 . Другими словами, 0,1 не совсем равно 1/10 в компьютере.
Точно так же, когда мы бежимround()Функция также является приблизительной величиной, фактически сохраненной в компьютере. 2,67 на самом деле примерно 2.67499999999999982236431605997495353221893310546875 , Вы видите, что третий десятичный знак равен 4, затем round (2,675, 2) эквивалентен round (2,674, 2), и результат, конечно же, равен 2,67. Стоит отметить, что это явление широко распространено на различных компьютерах и на разных языках программирования. Это не ошибка, но некоторые языки решили не показывать вам это.
3.3 Округление в Java
Java предоставляет методы floor и ceil для округления в большую и меньшую сторону.
Эти две функции просты и удобны, они необходимы для домашних путешествий. Кроме того, в Java есть функция округления, которая может реализовывать различные сложные округления.
System.out.println(Math.round(0.5)); // Вывод 1 System.out.println(Math.round(-0.5)); // Вывод 0 System.out.println(Math.round(-0.51)); // Вывод -1``` Что за чертовщина! Сохраняйте спокойствие и продолжайте! Существует множество различных стратегий округления в математике, например, метод округления, который преподает наш учитель физкультуры. Общей чертой различных стратегий округления является приблизительное значение истинности, что вносит систематическую ошибку. Очевидно, что округление - не честная стратегия (подумайте о округлении от 0 до 4 и получении от 5 до 9). Есть что-то под названием Banker’s Rounding. Вы когда-нибудь слышали о нем? Во всяком случае, я узнал об этом совсем недавно. Фактически, и .NET, и VB6 используют этот метод по умолчанию, а IEEE 754 использует это округление по умолчанию. Banker’s Rounding - это еще и стратегия равномерного раунда. Предполагая, что текущая рассматриваемая цифра - d (фактически, d - первая цифра, которая не будет зарезервирована), если d 5, округлить от нуля; Когда d == 5, это по цифрам до и после d необходимо определить, какую сторону принять. > 1) Если после d стоит ненулевая цифра, введите; 2) Если после d нет ненулевой цифры, то посмотрите на цифру перед d, обозначенную c: A. Если c нечетное, введите; Б. Если c - четное число, отбросьте его. Давайте возьмем еще один каштан, оставим 0 десятичных знаков для следующих чисел, Первый десятичный знак - d, а целое число - c: >BankRound(0.4)==0, BankRound(0.6)==1, BankRound(-0.4)==0, BankRound(-0.6)==-1 BankRound(1.5)==2.0, BankRound(-1.5)==-2.0, BankRound(2.5)==2.0, BankRound(-2.5)==-2.0 BankRound(1.51)==2.0, BankRound(-1.51)==-2.0, BankRound(2.51)==3.0, BankRound(-2.51)==-3.0 Видно, что Banker’s Rounding обрабатывает положительные и отрицательные числа симметрично, поэтому не вносит отклонений, вызванных знаками. Кроме того, он округляет цифры с равной вероятностью (учитывая, что c и c имеют половину шансов и четных чисел), разница от истинного значения после нескольких раундов будет небольшой. После стольких разговоров, какое отношение это имеет к ** Math.round () ** в Java? Я также написал это и обнаружил, что мягких (луанских) отношений, похоже, не существует. Потому что это не последовало за округлением Банкира. Вместо этого выполните округление в соответствии со следующей стратегией: Если рассматриваемая цифра d не 5, округлить d 5. Когда d == 5: > a. Если справа от d есть ненулевые цифры, введите; > b. Если справа от d нет ненулевых цифр, то ** округлять до верхнего предела **, то есть округлять до отрицательных чисел и округлять до положительных чисел. [Это указано в документации Java] (http://docs.oracle.com/javase/7/docs/api/java/lang/Math.html) Кроме того, в Java вы можете использовать ** BigDecimal ** и ** RoundingMode ** для достижения более общего метода округления. ```java double d=-2.5; BigDecimal bd=new BigDecimal(d); double nd=bd.setScale(0, RoundingMode.HALF_EVEN).doubleValue(); System.out.println(nd); // Вывод -2.0 '' ** Первый параметр setScale ** - это количество десятичных знаков, которые необходимо сохранить, а второй параметр - это режим округления. Дополнительные режимы округления: ** HALF_EVEN **, что является способом банкира; ** HALF_UP **, округление; ** HALF_DOWN **, округление до шести; ** ПОТОЛОК, ПОЛ ** в направлении положительной бесконечности и отрицательной бесконечности; ** ВВЕРХ, ВНИЗ ***, в сторону нуля и от нуля; ** НЕОБХОДИМО **, означает, что округленное значение равно исходному значению, то есть округление не требуется. Если утверждение неверно, создается исключение ArithmeticException. Сложно написать это вначале, но я надеюсь, что вы кое-что добьетесь. Добро пожаловать на обсуждение, говорите хорошо, если у вас есть что-то (╰ ( ̄ ▽  ̄) ╭) Эта статья соответствует [Соглашению Creative Commons: указание авторства - некоммерческое использование - разделение таким же образом (BY-NC-SA)] (http://creativecommons.org/licenses/by-nc-sa/3.0/cn /) и [ Книжное соглашение] (http://www.jianshu.com/p/c44d171298ce) Укажите: ** Автор [ ] (http://www.jianshu.com/users/5e81a35c8586/latest_articles) **
Округленное деление в java
Встроенные примитивные числовые типы не всегда могут подходить для определенных программ. Например, необходимо хранить и использовать в программе очень большие числа, которые выходят за пределы допустимых значений для типов long и double. В этом случае для работы с числовыми данными можно использовать два дополнительных типа из пакета java.math — BigInteger (для целочисленных данных) и BigDecimal (для чисел с плавающей точкой).
Основные методы класса BigInteger:
- BigInteger add(BigInteger other) : возвращает сумму двух чисел
- BigInteger subtract(BigInteger other) : возвращает разность двух чисел
- BigInteger multiply(BigInteger other) : возвращает произведение двух чисел
- BigInteger divide(BigInteger other) : возвращает частное двух чисел
- BigInteger mod(BigInteger other) : возвращает остаток от целочисленного деления двух чисел
- BigInteger sqrt() : возвращает квадратный корень числа
- int compareTo(BigInteger other) : сравнивает два числа. Возвращает -1, если текущий объект меньше числа other, 1 — если текущий объект больше и 0 — если числа равны
- static BigInteger valueOf(long x) : возвращает объект BigInteger, значение которого равно числу, переданному в качестве параметра
- int intValue() : конвертирует объект BigInteger в объект int
- byte byteValue() : преобразует объект BigInteger в byte
- short shortValue() : преобразует объект BigInteger в short
- long longValue() : преобразует объект BigInteger в long
Основные методы класса BigDecimal:
- BigDecimal add(BigDecimal other) : возвращает сумму двух чисел
- BigDecimal subtract(BigDecimal other) : возвращает разность двух чисел
- BigDecimal multiply(BigDecimal other) : возвращает произведение двух чисел
- BigDecimal divide(BigDecimal other) : возвращает частное двух чисел
- BigDecimal divide(BigDecimal other, RoundingMode mode) : результат деления двух чисел, округленное в соответствии с режимом mode
- int compareTo(BigDecimal other) : сравнивает два числа. Возвращает -1, если текущий объект меньше числа other, 1 — если текущий объект больше и 0 — если числа равны
- static BigDecimal valueOf(double x) : возвращает объект BigDecimal, значение которого равно числу, переданному в качестве параметра
- double doubleValue() : преобразует объект BigDecimal в double
- float floatValue() : преобразует объект BigDecimal в float
Пример использования классов BigInteger и BigDecimal:
import java.math.*; public class Program < public static void main(String[] args) < BigInteger a = BigInteger.valueOf(2147483647); BigInteger b = BigInteger.valueOf(2147483641); //a = a * b; // так нельзя a = a.multiply(b); System.out.println(a); // 4611686001247518727 long x = a.longValue(); System.out.println(x); // 4611686001247518727 BigDecimal c = BigDecimal.valueOf(2325.06); BigDecimal d = BigDecimal.valueOf(215.06); c = c.subtract(d.multiply(BigDecimal.valueOf(2.1))); System.out.println(c); // 1873.434 double y = c.doubleValue(); System.out.println(y); // 1873.434 >>
Стоит отметить, несмотря на то, что объекты BigInteger и BigDecimal представляют числа, мы не можем применять с ними стандартные арифметические операции. Все математические действия с данными объектами идут через их методы.