Как округлить числа в Python

Как округлить числа в Python

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

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

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

В этой статье вы узнаете:

  • Почему способ округления чисел важен

  • Как округлить число согласно различным стратегиям округления и как реализовать каждый метод в чистом Python

  • Как округление влияет на данные, и какая стратегия округления минимизирует этот эффект

  • Как округлить числа в массивах NumPy и Pandas DataFrames

  • Когда применять разные стратегии округления

    *__ Пройдите тест:* Проверьте свои знания с помощью нашего интерактивного теста «Округление чисел в Python». По окончании вы получите оценку, чтобы вы могли отслеживать прогресс в обучении с течением времени:

ссылка:/викторины/Python-округление/[принять викторину »]

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

Давайте начнем с рассмотрения встроенного в Python механизма округления.

Встроенная функция Python + round () +

Python имеет встроенную функцию + round () +, которая принимает два числовых аргумента, + n + и + ndigits +, и возвращает число + n +, округленное до + ndigits +. Аргумент + ndigits + по умолчанию равен нулю, поэтому, если его опустить, число округляется до целого числа. Как вы увидите, + round () + может работать не совсем так, как вы ожидаете.

То, как большинство людей учат округлять число, выглядит примерно так:

_ _ Округлите число + n + до + p + десятичных разрядов, сначала сместив десятичную точку в + n + на + p + мест, умножив + n + на 10ᵖ (10 повышается до степени + p + th ), чтобы получить новый номер + m +.

Затем посмотрите на цифру + d + в первом десятичном знаке + m +. Если + d + меньше 5, округлите + m + до ближайшего целого числа. В противном случае, округлить + m + вверх.

Наконец, сдвиньте десятичную точку назад местами + p +, разделив + m + на 10ᵖ. _ _

Это простой алгоритм! Например, число + 2.5 +, округленное до ближайшего целого числа, равно + 3 +. Число + 1.64 +, округленное до одного десятичного знака, равно + 1.6 +.

Теперь откройте сеанс интерпретатора и округлите + 2.5 + до ближайшего целого числа, используя встроенный в Python https://docs.python.org/3/library/functions.html#round [+ round () + ] функция:

>>>

>>> round(2.5)
2

Удушье!

Как + round () + обрабатывает число + 1.5 +?

>>>

>>> round(1.5)
2

Итак, + round () + округляет + 1.5 + до + 2 +, а + 2.5 + до + 2 +!

Прежде чем вы поднимите проблему с трекером ошибок Python, позвольте мне заверить вас, что + round (2.5) + должен возвращать + 2 +. Есть веская причина, почему + round () + ведет себя так же, как и он.

Из этой статьи вы узнаете, что существует больше способов округлить число, чем вы ожидаете, каждый из которых имеет свои уникальные преимущества и недостатки. + round () + ведет себя в соответствии с определенной стратегией округления, которая может или не может быть той, которая вам нужна в данной ситуации.

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

Какое влияние может оказать округление?

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

Стоимость акций зависит от спроса и предложения. Чем больше людей хотят купить акции, тем больше их ценность, и наоборот. На фондовых рынках большого объема стоимость конкретной акции может колебаться в секунду.

Давайте проведем небольшой эксперимент. Мы будем притворяться, что общая стоимость приобретенных вами акций колеблется от небольшого случайного числа каждую секунду, например, от 0,05 до 0,05 доллара. Это колебание не обязательно может быть хорошим значением только с двумя десятичными знаками. Например, общая стоимость может увеличиться на 0,031286 долл. США за одну секунду и уменьшиться в следующую секунду на 0,028476 долл. США.

Вы не хотите отслеживать свою ценность до пятого или шестого знака после запятой, поэтому вы решили отрубить все после третьего знака после запятой. На жаргонном языке это называется усечением числа до третьего знака после запятой. Здесь следует ожидать некоторую ошибку, но, сохраняя три знака после запятой, эта ошибка не может быть существенной. Правильно?

Чтобы запустить наш эксперимент с использованием Python, давайте начнем с написания функции + truncate () +, которая усекает число до трех десятичных знаков:

>>>

>>> def truncate(n):
...     return int(n * 1000)/1000

Функция + truncate () + работает, сначала сдвигая десятичную точку в числе + n + на три позиции вправо, умножая + n + на + 1000 +. Целая часть этого нового числа берется с помощью + int () +. Наконец, десятичная точка сдвигается на три позиции назад влево путем деления + n + на + 1000 +.

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

Начните с инициализации этих переменных в + 100 +:

>>>

>>> actual_value, truncated_value = 100, 100

Теперь давайте запустим симуляцию в течение 1 000 000 секунд (примерно 11,5 дней). Для каждой секунды генерируйте случайное значение между + -0.05 + и + 0.05 + с помощью функции +iform () + в модуле + random +, а затем обновляйте + actual + и `+ truncated + `:

>>>

>>> import random
>>> random.seed(100)

>>> for _ in range(1000000):
...     randn = random.uniform(-0.05, 0.05)
...     actual_value = actual_value + randn
...     truncated_value = truncate(truncated_value + randn)
...

>>> actual_value
96.45273913513529

>>> truncated_value
0.239

Основная часть симуляции происходит в цикле + for +, который проходит по диапазону + (1000000) + чисел между + 0 + и + 999,999 +. Значение, взятое из + range () + на каждом шаге, сохраняется в переменной + _ +, которую мы используем здесь, потому что нам фактически не нужно это значение внутри цикла.

На каждом шаге цикла новое случайное число между + -0.05 + и + 0.05 + генерируется с использованием + random.randn () + и присваивается переменной + randn +. Новое значение ваших инвестиций рассчитывается путем добавления + randn + к + actual_value +, а усеченная сумма вычисляется путем добавления + randn + к + truncated_value + и затем обрезания этого значения с помощью + truncate () + ,

Как вы можете видеть, проверив переменную + actual_value + после запуска цикла, вы потеряли всего около $ 3,55. Однако, если бы вы смотрели на + truncated_value +, вы бы подумали, что потеряли почти все свои деньги!

*Примечание:* В приведенном выше примере функция `+ random.seed () +` используется для заполнения генератора псевдослучайных чисел, чтобы вы могли воспроизвести вывод, показанный здесь.

Чтобы узнать больше о случайности в Python, ознакомьтесь с Generating Random Data в Python (Руководство).

Не обращая внимания на момент, когда + round () + не ведет себя так, как вы ожидаете, давайте попробуем повторно запустить симуляцию. Мы будем использовать + round () + на этот раз для округления до трех знаков после запятой на каждом шаге и + seed () + для симуляции снова, чтобы получить те же результаты, что и раньше:

>>>

>>> random.seed(100)
>>> actual_value, rounded_value = 100, 100

>>> for _ in range(1000000):
...     randn = random.uniform(-0.05, 0.05)
...     actual_value = actual_value + randn
...     rounded_value = round(rounded_value + randn, 3)
...

>>> actual_value
96.45273913513529

>>> rounded_value
96.258

Какая разница!

Как ни шокирует, эта точная ошибка вызвала настоящий ажиотаж в начале 1980-х годов, когда система, предназначенная для записи значения Vancouver Stock Exchange, усекла общее значение индекса до трех знаков после запятой вместо округления. Ошибки округления имеют http://mate.uprh.edu/~pnegron/notas4061/par Parliament.htm[swayed выборы] и даже приводят к http://www-users.math.umn.edu/~arnold/disasters/patriot .html [гибель людей].

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

Зверинец методов

Существует plethora стратегий округления, каждый из которых имеет свои преимущества и недостатки. В этом разделе вы узнаете о некоторых наиболее распространенных методах и о том, как они могут повлиять на ваши данные.

сокращение

Самый простой, хотя и самый грубый метод округления числа - это усечение числа до заданного числа цифр. Когда вы усекаете число, вы заменяете каждую цифру после данной позиции на 0. Вот некоторые примеры:

Value Truncated To Result

12.345

Tens place

10

12.345

Ones place

12

12.345

Tenths place

12.3

12.345

Hundredths place

12.34

Вы уже видели один способ реализовать это в функции + truncate () + по ссылке: # what-much-effect-can-rounding-have [Какое влияние может иметь округление?]. В этой функции входное число было усечено до трех знаков после запятой:

  • Умножая число на + 1000 +, чтобы сдвинуть десятичную точку на три позиции вправо

  • Взятие целой части этого нового числа с помощью + int () + *Сдвиг десятичного знака на три позиции назад влево путем деления на «+ 1000 +»

Вы можете обобщить этот процесс, заменив + 1000 + числом 10ᵖ (+ 10 +, возведенное в степень pth), где p - количество десятичных разрядов, до которых нужно усечь:

def truncate(n, decimals=0):
    multiplier = 10*  *decimals
    return int(n* multiplier)/multiplier

В этой версии + truncate () + второй аргумент по умолчанию равен + 0 +, так что если второй аргумент не передан функции, то + truncate () + возвращает целую часть любого числа перешел на это.

Функция + truncate () + хорошо работает как для положительных, так и для отрицательных чисел:

>>>

>>> truncate(12.5)
12.0

>>> truncate(-5.963, 1)
-5.9

>>> truncate(1.625, 2)
1.62

Вы можете даже передать отрицательное число в + decimals +, чтобы усечь до цифр слева от десятичной точки:

>>>

>>> truncate(125.6, -1)
120.0

>>> truncate(-1374.25, -3)
-1000.0

Когда вы усекаете положительное число, вы округляете его вниз. Аналогично, усечение отрицательного числа округляет это число. В некотором смысле усечение - это комбинация методов округления в зависимости от знака числа, которое вы округляете.

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

Округления

Вторая стратегия округления, которую мы рассмотрим, называется «округлением». Эта стратегия всегда округляет число до указанного количества цифр. Следующая таблица суммирует эту стратегию:

Value Round Up To Result

12.345

Tens place

20

12.345

Ones place

13

12.345

Tenths place

12.4

12.345

Hundredths place

12.35

Для реализации стратегии «округления» в Python мы будем использовать функцию https://docs.python.org/3/library/math.html#math.ceil [+ ceil () +] из https. ://docs.python.org/3/library/math.html [+ math +] модуль.

Функция + ceil () + получила свое название от термина «потолок», который используется в математике для описания ближайшего целого числа, которое больше или равно заданному числу.

Каждое число, которое не является целым числом, лежит между двумя последовательными целыми числами. Например, число + 1.2 + лежит в интервале между + 1 + и + 2 +. «Потолок» - это наибольшая из двух конечных точек интервала. Меньшая из двух конечных точек называется «этаж». Таким образом, потолок + 1.2 + равен + 2 +, а пол + 1.2 + равен + 1 +.

В математике специальная функция, называемая функция потолка , отображает каждое число на его потолок. Чтобы функция потолка могла принимать целые числа, потолок целого числа определяется как само целое число. Таким образом, потолок числа + 2 + равен + 2 +.

В Python + math.ceil () + реализует функцию потолка и всегда возвращает ближайшее целое число, которое больше или равно его вводу:

>>>

>>> import math

>>> math.ceil(1.2)
2

>>> math.ceil(2)
2

>>> math.ceil(-0.5)
0

Обратите внимание, что потолок + -0.5 + равен + 0 +, а не + -1 +. Это имеет смысл, поскольку + 0 + является ближайшим целым числом к ​​+ -0.5 +, которое больше или равно + -0.5 +.

Давайте напишем функцию с именем + round_up () +, которая реализует стратегию «округления»:

def round_up(n, decimals=0):
    multiplier = 10 * *decimals
    return math.ceil(n* multiplier)/multiplier

Вы можете заметить, что + round_up () + очень похож на + truncate () +. Во-первых, десятичная точка в + n + сдвигается на правильное число мест вправо путем умножения + n + на +10 * десятичных дробей +. Это новое значение округляется до ближайшего целого числа с использованием + math.ceil () +, а затем десятичная точка сдвигается назад влево путем деления на +10