Округление в python
Содержание:
- Работающие реализации на Go
- Метод Math.round() java
- Потеря точности при работе с вещественными числами
- Привязка к диапазону
- Применения
- Округление чисел с плавающей запятой с помощью DoubleRounder
- Встроенные функции
- Работа с округленными числами
- Правила округления
- Round() в Go 1.10
- Зачем нужно округление
- Как грамотно округлить число в Excel
- Ошибка округления, вызванная арифметикой с плавающей запятой
Работающие реализации на Go
Round(), используемая в Postgres
Выше я уже упоминал, что в Postgres содержится код функции Round() на C, который работает для всех тестируемых значений. В CockroachDB мы , без комментариев он выглядит следующим образом:
Давайте разберёмся, как он работает. Первые шесть строк обрабатывают особые случаи. Далее мы выбираем roundFn из Ceil и Floor в зависимости от того, положительное число или отрицательное. Далее начинается самое интересное:
Этим кодом мы сдвигаем x ближе к нулю.
Далее мы проверяем, не стал ли x в точности нулём и не поменялся ли у него знак. Это означает что исходное число <= 0,5, в этом случае мы возвращаем ноль с нужным знаком.
Эта проверка нужна для очень больших чисел, для которых x-0,5 == x-1,0, в этих случаях мы можем вернуть число неизменённым.
Далее мы округляем число с помощью Floor() или Ceil() и возвращаем это значение, если оно отличается от x, что может случиться, только если дробная часть входного значения не равна в точности 0,5, так как выше мы вычли 0,5 из него.
Теперь мы знаем, что дробная часть равна 0,5, поэтому нам нужно округлить до ближайшего чётного числа (реализация Round() в Postgres в этом месте отличается от приведённых выше вариантов). Комментарий в коде лучше это описывает:
Чтобы сохранить оригинальное поведение, этот код можно заменить на следующий:
github.com/montanaflynn/stats
Ещё одна работающая реализация содержится в пакете github.com/montanaflynn/stats. Без комментариев она выглядит следующим образом:
Ключевое отличие от предыдущих решений заключается в использовании функции Modf(), которая корректно разделяет целую и дробную части чисел.
Метод Math.round() java
При использовании метода Math.round() можно контролировать п-количество десятичных разрядов путем умножения и деления на 10^п :
public static double roundAvoid(double value, int places) { double scale = Math.pow(10, places); return Math.round(value * scale) / scale; }
Этот метод не рекомендуется использовать для округления чисел, поскольку он усекает значение. Во многих случаях значения округляются неправильно:
System.out.println(roundAvoid(1000.0d, 17)); // Вывод: 92.23372036854776 !! System.out.println(roundAvoid(260.775d, 2)); // Вывод: 260.77 вместо ожидаемого 260.78
Потеря точности при работе с вещественными числами
При работе с вещественными числами всегда нужно иметь в виду, что вещественные числа не точные. Всегда будут ошибки округления, ошибки преобразования из десятичной системы в двоичную и, наконец, самое частое – потеря точности при сложении/вычитании чисел слишком разных размерностей.
Последнее — самая неожиданная ситуация для новичков в программировании.
Если из числа вычесть , мы получим опять .
Вычитание чисел слишком разных размерностей | Объяснение |
---|---|
Второе число слишком маленькое, и его значащая часть игнорируется (выделено серым). Оранжевым выделены 15 значащих цифр. |
Что тут сказать, программирование — это не математика.
Привязка к диапазону
Иногда нужно получить значение х, которое должно находиться в пределах определенного диапазона. Например, нужно значение от 1 до 100, но мы получаем значение 123. Чтобы исправить это, можно использовать min() (возвращает наименьшее из чисел) и max (возвращает максимально допустимое число).
Использование:
var lowBound = 1; var highBound = 100; var numInput = 123; var clamped = Math.max(lowBound, Math.min(numInput, highBound)); console.log(clamped); > 100;
Можно создать функцию или расширение класса Number:
Number.prototype.clamp = function(min, max) { return Math.min(Math.max(this, min), max); };
Использование:
(numInput).clamp(lowBound, highBound);
Применения
Округление используется для того, чтобы работать с числами в пределах того количества знаков, которое соответствует реальной точности параметров вычислений (если эти значения представляют собой измеренные тем или иным образом реальные величины), реально достижимой точности вычислений либо желаемой точности результата. В прошлом округление промежуточных значений и результата имело прикладное значение (так как при расчётах на бумаге или с помощью примитивных устройств типа абака учёт лишних десятичных знаков может серьёзно увеличить объём работы). Сейчас оно остаётся элементом научной и инженерной культуры. В бухгалтерских приложениях, кроме того, использование округлений, в том числе промежуточных, может требоваться для защиты от вычислительных ошибок, связанных с конечной разрядностью вычислительных устройств.
Более того, некоторые исследования используют округления возраста для измерения числовой грамотности. Это связано с фактом, что менее образованные люди склонны округлять свой возраст вместо того, чтобы указывать точный. Например, в официальных записях населения с более низким уровнем человеческого капитала чаще встречается возраст 30, чем 31 или 29.
Округление чисел с плавающей запятой с помощью DoubleRounder
DoubleRounder — это утилита из библиотеки decimal4j. Она предоставляет быстрый метод округления double чисел до 18 знаков после запятой.
Последнюю версию библиотеки можно найти здесь. Чтобы подключить ее, добавьте зависимость в файл pom.xml:
<dependency> <groupId>org.decimal4j</groupId> <artifactId>decimal4j</artifactId> <version>1.0.3</version> </dependency>
Пример использования утилиты:
DoubleRounder.round(PI, 3);
Но DoubleRounder дает сбой в нескольких сценариях. Например:
System.out.println(DoubleRounder.round(256.025d, 2)); // OUTPUTS: 256.02 вместо ожидаемого 256.03
Встроенные функции
Для операции округления в Python есть встроенные функции – и
round
– округляет число (number) до ndigits знаков после запятой. Это стандартная функция, которая для выполнения не требует подключения модуля math.
По умолчанию операция проводится до нуля знаков – до ближайшего целого числа. Например:
Чтобы получить целый показатель, результат преобразовывают в .
Синтаксически функция вызывается двумя способами.
- – это округление числа до целого, которое расположено ближе всего. Если дробная часть равна 0,5, то округляют до ближайшего четного значения.
- – данные округляют до знаков после точки. Если округление проходит до сотых, то равен «2», если до тысячных – «3» и т.д.
int
– встроенная функция, не требующая подключения дополнительных модулей. Её функция – преобразование действительных значений к целому путем округления в сторону нуля. Например
Для положительных чисел функция аналогична функции , а для отрицательных – аналогично . Например:
Чтобы число по int преобразовать по математическим правилам, нужно выполнить следующие действия.
- Если число положительное, добавить к нему 0,5.
- Если число отрицательное, добавить -0,5.
Синтаксически преобразование оформляется так:
Работа с округленными числами
Округление уже округленных чисел
Если исходное число уже является результатом округления, то для пограничного случая, когда новая цифра округления равна 5 (и все цифры после этого нуля), по возможности следует использовать неокругленное число (например, с математическими константами):
Известное неокругленное число: 13.374999747, округленное начальное число: 13.3750
- → число округлено: 13,37
Неокругленное число неизвестно, начальное число округлено: 13.3750
- → округленное число: 13,38.
Идентификация результатов округления
В научных статьях и таблицах логарифмов иногда указывается, была ли последняя цифра получена округлением в большую или меньшую сторону. Число, полученное округлением в большую сторону, обозначается линией под (или над) числом, число, которое не было изменено округлением (число было округлено), отмечается точкой над числом.
Примеры:
- 3,4134928 …{\ displaystyle 3 {,} 4134928 …}становится к ; это число — новые раунды . При повторном округлении (в примере до трех знаков после запятой) необходимо округлять в меньшую сторону.3,4135_{\ displaystyle 3 {,} 413 {\ underline {5}}}3,413{\ displaystyle 3 {,} 413}
- 2,6245241 …{\ displaystyle 2 {,} 6245241 …}становится к ; это число станет яснее при следующем округлении до . При повторном округлении (в примере до трех знаков после десятичной точки) вам необходимо округлить в большую сторону. Для дальнейшего округления (здесь до двух мест) оно будет округлено в меньшую сторону, обозначенное цифрой 5 .2,6245˙{\ displaystyle 2 {,} 624 {\ dot {5}}}2,625{\ displaystyle 2 {,} 625}2,625_{\ displaystyle 2 {,} 62 {\ underline {5}}}
Если другие цифры не известны, предполагается, что начальный номер является точным.
Расчет с округленными числами
Если в расчет включены округленные числа, окончательный результат должен быть округлен до того же количества значащих цифр. Если z. Например, если измеряется сила 12,2 Ньютона, все окончательные результаты, зависящие от этой силы, должны быть округлены так, чтобы осталось не более трех значащих цифр. Таким образом, читатель не претендует на то, чтобы быть более точным, чем то, что на самом деле доступно.
Правила округления
Коммерческое округление
В Коммерческие туры (не отрицательные числа) выглядит следующим образом :
- Если число в первом десятичном разряде равно 0, 1, 2, 3 или 4, оно округляется в меньшую сторону.
- Если число в первом десятичном разряде — 5, 6, 7, 8 или 9, то оно округляется в большую сторону.
Это правило округления описано в стандарте DIN 1333 . Округление часто уже преподается в начальной школе.
Примеры (округление до двух знаков после запятой):
- 13,3749 … € ≈ 13,37 €
- 13,3750 … € ≈ 13,38 €
Отрицательные числа в зависимости от их величины округлой формы, на 5 , чтобы сказать от нуля ( Engl : от нуля ):
- −13,3749 … € ≈ −13,37 €
- −13,3750 … € ≈ −13,38 €
В Коммерческих турах частично в правовой среде , как гражданские раунды , называемых и г. Б. в о поставщиках государственных услуг пояснил следующее:
Симметричное закругление
Коммерческое и симметричное округление отличаются друг от друга только тем, что число округляется точно посередине между двумя числами с выбранным количеством десятичных цифр.
Симметричные (или геодезическим, математический, искажаются, научный ) округление определяются следующим образом (композиция адаптирована):
- Если число в первом десятичном разряде равно 0, 1, 2, 3 или 4, оно округляется в меньшую сторону.
- Если число представляет собой 5 (за которыми следуют другие цифры, которые не равны нулю), 6, 7, 8 или 9 в первом десятичном разряде, оно округляется в большую сторону.
- Если цифра в первом десятичном разряде, которую следует опустить, представляет собой только 5 (или 5, за которой следуют только нули), она округляется таким образом, чтобы последняя сохраняемая цифра была четной.
Этот тип округления используется в числовой математике , инженерии и технике. Он предусмотрен стандартом IEEE 754 для вычислений с двоичными числами с плавающей запятой в компьютерах. В англоязычной литературе это называется Round to Even или Banker’s Rounding .
Примеры (округление до одного десятичного знака):
- 2,2499 ≈ 2,2 (по правилу 1)
- 2,2501 ≈ 2,3 (по правилу 2)
- 2,2500 ≈ 2,2 (округлено до четного числа согласно правилу 3)
- 2,3500 ≈ 2,4 (округлено до четного числа согласно правилу 3)
Коммерческое округление приводит к небольшим систематическим ошибкам, так как округление на 0,5 происходит в большую сторону, а в меньшую сторону на 0,5 никогда не происходит; это может немного исказить статистику. Математическое округление всегда округляется в большую или меньшую сторону от точной середины между двумя цифрами до следующей четной цифры. В результате среднее значение округляется вверх и вниз примерно так же часто, по крайней мере, если исходные числа являются стохастическими . (Контрпример: если маленькие числа встречаются чаще, чем большие, их можно систематически округлять в меньшую сторону, чем в большую, см . Закон Бенфорда .)
Округление с сохранением суммы
В случае округления с сохранением суммы слагаемые округляются так, чтобы их сумма была равна округленной сумме слагаемых. Может потребоваться округлить некоторые слагаемые от ближайшего округленного значения до противоположного значения.
Важными приложениями являются распределение мест в пропорциональном представительстве и распределение всего НДС в счете-фактуре по его отдельным позициям.
Случай, когда все слагаемые положительные, был тщательно исследован, см. Процедуру распределения мест .
Метод Харе-Нимейера может быть обобщен для слагаемых с обоими знаками : вы округляете все числа до ближайших круглых чисел, и пока сумма слишком велика (или слишком мала), вы выбираете одно из округленных (или округленных) чисел. ) нумерует с наибольшим округление (или самое большое количество округления вниз) и изменяет его округления в направлении , противоположном. Это означает, что сумма изменений минимальна .
Round() в Go 1.10
Для тех, кто не знаком с устройством float (я в их числе), этот код выглядит совершенно непонятно. Попробуем разобраться, что же он делает:
Похоже, что мы берём битовое представление числа, сдвигаем его и применяем маску. Согласно :
Рассматривая приведённые выше константы, мы видим, что сдвиг составляет 64 — 11 — 1, что означает 64 бита на число, 11 из которых используются для показателя степени, один — для знака и 52 оставшихся бита — для мантиссы. Это означает, что используемый сдвиг удаляет биты мантиссы, а маска удаляет бит знака, оставляя нас только с показателем степени.
В полученном числе показатель степени записан не как он есть, а с прибавлением числа 1023 (это делается для того чтобы записывать отрицательные показатели для очень маленьких чисел), что означает, что мы должны вычесть 1023 из e, вычисленного выше, чтобы получить фактический показатель. Иными словами, если e < bias, то мы имеем отрицательный показатель степени, что означает, что абсолютное значение float должно быть < 1. Действительно, дальше мы видим:
Здесь бит маскируется знаковым битом, это используется только для сохранения правильного знака: теперь мы можем полностью игнорировать мантиссу. Мы можем это сделать, потому что в этом случае нас интересует только показатель степени. Так как используется основание степени 2, а e < bias, мы знаем, что наименьший показатель, который может быть, равен -1, а 2 ^ -1 = 0,5. Кроме того, мантисса имеет некоторое значение 1.X. Таким образом, в зависимости от показателя наше число находится либо в диапазоне (0,5, 1), либо в диапазоне (0, 0,5). Поэтому во втором случае для правильного округления нам нужно добавить к числу единицу. Фух. Подробнее это описано в википедии.
Теперь разберём второй случай:
Наверное, вы думаете, что условие в этой ветке должно быть e > bias, чтобы покрыть все случаи с положительным показателем степени. Но вместо этого тут используется только их часть. Использование сдвига здесь особенно интересно, потому что кажется, что оно несравнимо с bias. Первое — это число битов смещения, а второе — численное смещение. Но, поскольку числа с плавающей точкой представлены как (1.мантисса) * 2 ^ X, то если X больше числа битов в мантиссе, мы гарантированно получим значение без дробной части. То есть показатель степени сместил десятичную точку вправо настолько, что мантисса окончательно пропала. Таким образом, выражение в этой ветке игнорирует числа с плавающей точкой, которые уже округлены.
Первая строка тут простая: вычитаем bias из e и получаем реальное значение показателя степени. Вторая строка добавляет к значению 0,5. Это работает, потому что старший бит мантиссы добавляет 0,5 к финальной сумме (см. представление в статье “Википедии” ниже). В этом случае эта сумма переполняет 52-битные границы мантиссы, показатель степени будет увеличен на 1. Значение показателя степени не сможет переполниться до знакового бита, так как оно не может быть больше bias+shift из примера выше. В любом случае, дробная часть очищается. Таким образом, если дробная часть была больше или равна 0,5, она будет увеличена на 1, в противном случае будет отброшена. Хитро и не очевидно до тех пор, пока мы не посмотрим глубже.
Зачем нужно округление
Округлять числа необходимо для точности измерений. В некоторых сферах жизни погрешности в расчетах могут иметь очень серьезные последствия. Для этого существует метрология — наука, изучающая правила округления чисел и погрешности.
Приведем несколько примеров, в которых неправильное округление не приведет ни к чему страшному:
Средняя зарплата в нашей стране. Очень интересный показатель, который постоянно меняется. Например, по данным за 2015 год, средняя зарплата составила 32560 рублей. Если выражать в тысячах, получится число 32,56. Согласно математическим правилам его можно округлить до 33. После чего вынести официальную версию, что средняя зарплата равна 33 тысячам рублей.
Стоимость покупки. В каждом супермаркете можно увидеть товар со стоимостью, например, 48 рублей и 60 копеек. Если вы хотите совершить много покупок, логично будет прибавить к общей сумме 49 или даже 50 рублей. Это избавит вас от неловких ситуаций, когда вам не хватает совсем немного для оплаты покупки. А также сохранит вам лишнюю мелочь, которая может пригодиться потом.
Показания весов, как правило, ошибаются на 0,5—1 процент. Соответственно, если вы встали на весы, и они показали 50 килограммов, значит, вы можете весить на 500 граммов больше или меньше, чем увидели на шкале прибора. Согласитесь, ничего страшного в этом нет. Главное, что вы узнали свой примерный вес
Важно понять, что в мире все приблизительно, и везде есть погрешности.
Средний балл — самая распространённая ситуация. Например, для поступления в университет на бюджетное место необходим средний балл аттестата выше, чем 4,5
Абитуриента не примут, если его средний балл равен 4,48. По математическим правилам 4,48 можно округлить до четырёх с половиной. Однако в жизни такие правила не всегда работают.
Однако есть ситуации, где правильное округление является необходимостью. Наверняка читатель мог подумать, зачем нужна какая-то наука об округлении? Ведь все просто — округлять можно как в большую, так и в меньшую сторону, в зависимости от личной выгоды. Такой принцип применим не ко всем сферам жизни. Науку об округлении в первую очередь необходимо изучать инженерам-электроникам.
Люди, которые учились в технических институтах, знают, что при разработке определенных приборов необходимо провести много различных расчетов. Чаще всего промежуточными результатами этих расчетов являются нецелые числа. Чтобы они не повлияли на конечный результат, их нужно округлять только по определённым правилам либо вообще этого не делать, а работать с конечным результатом.
Суть в том, что погрешность может быть довольно велика (около 5 процентов), и это может плохо кончиться. Например, посчитанное значение напряжения тока в электрической цепи может быть неподходящим, и техническое устройство работать не будет. Или того хуже, инженера может ударить током.
Чтобы избежать подобных казусов, студентам технических вузов и инженерам необходимо знать правила округления.
Как грамотно округлить число в Excel
В нашем случае округление было осуществлено в сторону увеличения. Это зависит от числа, которое убирается. Если перед нужным значением находится 5 или больше, то округление осуществляется в направлении увеличения, а если меньше – уменьшения. Все так, как нужно делать в математике, никаких изменений в правилах нет.
Точность результата зависит от того, сколько знаков в дробной части человек решил оставить. Чем оно больше, тем выше точность. Поэтому настоятельно рекомендуется выполнять округление значений лишь в тех ситуациях, когда в этом есть реальная практическая необходимость. Иногда даже малейшее округление может абсолютно исказить расчеты. Это, кстати, одна из наиболее распространенных причин, почему так часто синоптики ошибаются. Даже был открыт эффект бабочки, когда из-за незначительных различий между округленным значением и настоящим был спрогнозирован дождливый сезон.
Ошибка округления, вызванная арифметикой с плавающей запятой
Даже если некоторые числа могут быть представлены точно числами с плавающей запятой и такие числа называются машинными числами , выполнение арифметических операций с плавающей запятой может привести к ошибке округления в окончательном результате.
Добавление
Машинное сложение состоит из выравнивания десятичных знаков двух добавляемых чисел, их сложения и последующего сохранения результата как числа с плавающей запятой. Само сложение может быть выполнено с более высокой точностью, но результат должен быть округлен до указанной точности, что может привести к ошибке округления.
Например, при добавлении к двойной точности IEEE следующим образом ,
1 {\ displaystyle 1} 2 — 53 {\ displaystyle 2 ^ {- 53}}
1,00 … × 2 + 1,00 … × 2 — 53 знак равно 1. 00 … ⏟ 52 бит × 2 + 00 … ⏟ 52 бит 1 × 2 знак равно 1. 00 … ⏟ 52 бит 1 × 2 {\ displaystyle {\ begin {align} 1,00 \ ldots 0 \ times 2 ^ {0} +1,00 \ ldots 0 \ times 2 ^ {- 53} & = 1. \ underbrace {00 \ ldots 0} _ {\ text { 52 бита}} \ times 2 ^ {0} +0. \ Underbrace {00 \ ldots 0} _ {\ text {52 бит}} 1 \ times 2 ^ {0} \\ & = 1. \ underbrace {00 \ ldots 0} _ {\ text {52 бита}} 1 \ times 2 ^ {0} \ end {выровнено}}}
Это сохраняется, поскольку в стандарте IEEE используется округление до ближайшего. Поэтому, равно двойной точности IEEE и округление ошибка . 1. 00 … 0 ⏟ 52 бит × 2 0 {\ displaystyle 1. \ underbrace {00 \ ldots 0} _ {\ text {52 бит}} \ times 2 ^ {0}} 1 + 2 — 53 {\ displaystyle 1 + 2 ^ {- 53}} 1 {\ displaystyle 1} 2 — 53 {\ displaystyle 2 ^ {- 53}}
Из этого примера видно, что при сложении большого числа и малого числа может возникнуть ошибка округления, поскольку сдвиг десятичных знаков в мантиссах для согласования показателей степени может вызвать потерю некоторых цифр.
Умножение
Как правило, произведение мантисс с -цифрами содержит до цифр, поэтому результат может не соответствовать мантиссе. Таким образом, в результат будет включена ошибка округления.
2 {\ displaystyle 2} п {\ displaystyle p} 2 п {\ displaystyle 2p}
Например, рассмотрим нормализованную систему счисления с плавающей запятой, в которой основание и цифры мантиссы не больше . Потом и
Обратите внимание, но поскольку там не более цифр мантиссы. Ошибка округления будет
β знак равно 10 {\ displaystyle \ beta = 10} 2 {\ displaystyle 2} ж л ( 77 ) знак равно 7,7 × 10 {\ displaystyle fl (77) = 7,7 \ times 10} ж л ( 88 ) знак равно 8,8 × 10 {\ displaystyle fl (88) = 8,8 \ times 10} 77 × 88 знак равно 6776 {\ displaystyle 77 \ times 88 = 6776} ж л ( 6776 ) знак равно 6,7 × 10 3 {\ displaystyle fl (6776) = 6,7 \ times 10 ^ {3}} 2 {\ displaystyle 2} 6776 — ж л ( 6776 ) знак равно 6776 — 6,7 × 10 3 знак равно 76 {\ displaystyle 6776-fl (6776) = 6776-6,7 \ times 10 ^ {3} = 76}
Разделение
Как правило, частное мантисс-цифр может содержать больше, чем -цифров. Таким образом, в результат будет включена ошибка округления.
2 {\ displaystyle 2} п {\ displaystyle p} п {\ displaystyle p}
Например, если приведенная выше нормализованная система счисления с плавающей запятой все еще используется, то но . Итак, хвост отрезан. 1 / 3 знак равно 0,333 … {\ Displaystyle 1/3 = 0,333 \ ldots} ж л ( 1 / 3 ) знак равно ж л ( 0,333 … ) знак равно 3.3 × 10 — 1 {\ displaystyle fl (1/3) = fl (0,333 \ ldots) = 3,3 \ times 10 ^ {- 1}} 0,333 … — 3.3 × 10 — 1 знак равно 0,00333 … {\ displaystyle 0,333 \ ldots -3,3 \ times 10 ^ {- 1} = 0,00333 \ ldots}
Субтрактивная отмена
Вычитание двух почти равных чисел называется вычитанием .
- Когда первые цифры отменяются, результат может быть слишком маленьким для точного представления, и он будет представлен просто как .
{\ displaystyle 0}Например, let и здесь используется второе определение машинного эпсилон. Какое решение ? Известно, что и почти равны числа, и . Однако в системе счисления с плавающей запятой . Несмотря на то, что он достаточно большой, чтобы его можно было представить, оба экземпляра были округлены в виде дачи . | ϵ |
- Даже при несколько большем значении результат в типичных случаях все равно существенно ненадежен. Нет особой веры в точность значения, потому что наибольшая неопределенность в любом числе с плавающей запятой — это цифры в крайнем правом углу.
ϵ {\ displaystyle \ epsilon}Например, . Результат наглядно представим, но веры в него нет. 1,99999 × 10 2 — 1,9998 × 10 2 знак равно 0,00001 × 10 2 знак равно 1 × 10 — 5 × 10 2 знак равно 1 × 10 — 3 {\ displaystyle 1.99999 \ times 10 ^ {2} -1.99998 \ times 10 ^ {2} = 0.00001 \ times 10 ^ {2} = 1 \ times 10 ^ {- 5} \ times 10 ^ {2} = 1 \ times 10 ^ {- 3}} 1 × 10 — 3 {\ displaystyle 1 \ times 10 ^ {- 3}}