Python модуль числа: 6 способов найти модуль числа в Python 3 — Юрыч BRO на vc.ru

6 способов найти модуль числа в Python 3 — Юрыч BRO на vc.ru

Вступление

8511 просмотров

Всем начинающим кодерам привет!

Модуль числа… Это, казалось бы, простая вещь… да, так оно и есть. Тем не менее — всегда интересно поэкспериментировать и по-новому взглянуть на простое.

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

1 способ

Для начала самое очевидное. Проверяем отрицательное число (назовем его x) или положительное, т.е. <0 или нет. В случае отрицательного значения x, его нужно умножить на -1. Можно так:

def abs1(x): if x < 0: return x*(-1) return x

А можно заменить умножение унарным минусом:

def abs1(x): if x < 0: return -x return x

2 способ

Самое короткое решение в нашей статье — найти максимум между x и -x. Таким образом результат всегда будет положительным:

def abs2(x): return max(-x, x)

3 способ

Здесь мы проверяем строку на наличие в ней минуса. Изначально я хотел использовать метод isdigit(), но потом я понял, что метод не считает точку частью числа, поэтому для float в строке метод возвращает False. Поэтому:

​def abs3(x): if ‘-‘ in str(x): return -x return x

4 способ

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

def abs4(x): if ‘-‘ in str(x): return float(str(x)[1::]) return x

5 способ

Тут мы будем использовать факт того, что операция квадратного корня в Python всегда возвращает положительный результат. Эту операцию не обязательно брать из библиотеки Math, можно просто возвести число в с степень 0.

5. Итак:

def abs5(x): return (x*x)**0.5

6 способ

Здесь мы используем операции со строками, как в 4 способе. Отличие в том, что мы не проверяем строку на наличие минуса. Мы убираем уго, есть он в строке или нет. Метод replace() позволяет убрать все повторения одного символа, что для нас избыточно, но с нулем повторений он тоже работает:

def abs6(x): return float(str(x).replace(‘-‘, »))

Примечание: говоря про положительные значения, правильнее сказать — положительные или нулевые, но я решил не засорять текст такой мелочью.

Статистика быстродействия

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

Я измерил время работы данного куска кода, где i — одна из 6 функций.

for j in range(100000): a = (i(1), i(-1), i(1.0), i(-1.0))

И вот что получилось:

Что у нас по итогу? Худший результат показал 4 способ, неудивительно. Самый очевидный способ — первый, на 2 месте. С большим отрывом лидирует 5 вариант, 100000 повторений за 0.79 сек! Математика быстрее логического оператора if и операций со строками.

Заключение

Я надеюсь, что вам была интересна данная статья, и вы разобрались в теме. Если хотите меня дополнить — пишите в комментариях. Удачи в мире IT!

Модуль числа в Python – abs и fabs

upd:

Александр Зайков

14.2K

1

Содержание:развернуть

Запускаю китайскую реплику «ТАРДИС», и вот мы в пятом классе. На доске нарисована числовая ось, а на ней выделен отрезок. Его начало в точке 4, а конец — в 8. Учительница говорит, что длину отрезка можно найти путём вычитания координаты начала отрезка из координаты его конца. Вычитаем, получаем 4, и радуемся — мы нашли длину. Ура! 🎉

Перемещаемся на год вперёд, и там происходит странное: учительница выделяет мелом другой отрезок, но делает это в каком-то неправильном месте — левее точки с цифрой «0». Теперь перед нами старая задача, но с новыми числами и даже буквами: A, B, минус 4 и минус 8. Мы начинаем искать длину отрезка AB = [-4;-8]:

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

Что такое модуль числа

Теперь по-взрослому.

Модуль числа называют абсолютной величиной.

Для вещественных чисел модуль определяется так:

Формула модуля числа для вещественных чисел

Т.е. в любом случае, модуль — число большее или равное 0. Поэтому отрицательная длина в примере хитрой учительницы должна была быть взята по модулю:

Тогда дети бы увидели, что геометрический смысл модуля — есть расстояние. Это справедливо и для комплексных чисел, однако формальное определение для них отличается от вещественного:

, где z — комплексное число: z = x + iy.

В Python для нахождения модуля числа применяются две функции: fabs() из подключаемой библиотеки math и встроенная функция abs().

Abs

В то время как math.fabs() может оперировать только вещественными аргументами, abs() отлично справляется и с комплексными. Для начала покажем, что abs в python работает строго в соответствии с математическим определением.

# для вещественных чисел print(abs(-1)) print(abs(0)) print(abs(1)) > 1 > 0 > 1

Как видно, с вещественными числами всё в порядке. Перейдём к комплексным.

# для комплексных чисел print(complex(-3, 4)) print(abs(complex(-3, 4))) > (-3+4j) > 5.0

Если вспомнить, что комплексное число выглядит так: z = x + iy, а его модуль вычисляется по формуле:

, то можно без труда посчитать, что sqrt(3**2 + 4**2) действительно равно 5.0.

Можно заметить, что abs() возвращает значения разных типов. Это зависит от типа аргумента:

print(type(abs(1))) > <class 'int'> print(type(abs(1.0))) > <class 'float'> print(type(abs(complex(1. 0, 1.0)))) <class 'float'>

В этом кроется ещё одно отличие abs() от

fabs(). Функция из модуля math всегда приводит аргумент к вещественному типу, а если это невозможно сделать — выбрасывает ошибку:

print(type(math.fabs(complex(2,3)))) > TypeError: can't convert complex to float

Fabs

Для начала работы с fabs() необходимо импортировать модуль math с помощью следующей инструкции:

import math

Мы уже выяснили, что fabs() не работает с комплексными числами, поэтому проверим работу функции на вещественных:

print(math.fabs(-10)) print(math.fabs(0)) print(math.fabs(10)) > 10.0 > 0.0 > 10.0

Функция производит вычисления в соответствие с математическим определением, однако, в отличие от abs(), всегда возвращает результат типа float:

print(type(math.fabs(10))) > <class 'float'>

Основные свойства модулей

# Квадрат модуля = квадрату числа print(pow(4, 2) == pow(abs(4), 2)) > True # |x| = |-x| print(abs(-10) == abs(10)) > True # Модуль произведения = произведению модулей: |ab|=|a||b| print(math.
fabs(11 * 3) == math.fabs(11) * math.fabs(3)) > True # Аналогично для деления: |a/b|=|a|/|b| print(math.fabs(48/8) == math.fabs(48) / math.fabs(8)) > True # |a ** b| = |a| ** b print(abs(2 ** 10) == abs(2) ** 10) > True

И еще несколько важных неравенств:

  • m <= |m|
  • -|m| <= m
  • |m| >= 0
  • |m + n| <= |m| + |n|
  • |m – n| <= |m| + |n|
  • |m| — |n| <= |m + n|
  • |m + n| >= ||m| — |n||
  • |m – n| >= ||m| — |n||

чисел — Числовые абстрактные базовые классы — Документация по Python 3.11.3

Исходный код: Lib/numbers.py


Модуль номеров ( PEP 3141 ) определяет иерархию числовых абстрактные базовые классы, которые постепенно определяют больше операций. Ни один из типов, определенных в этом модуле, не предназначен для создания экземпляров.

класс номеров.Номер

Корень числовой иерархии. Если вы просто хотите проверить, является ли аргумент x — это число, неважно, какого рода, используйте isinstance(x, Number) .

Числовая башня

класс номеров.Комплекс

Подклассы этого типа описывают комплексные числа и включают операции которые работают на встроенном комплексе типа . Это: преобразования в сложный и логический , реальный , образ , + , - , *, / , ** , абс() , сопряженное() , == , и != . Все, кроме

- и != , являются абстрактными.

настоящий

Реферат. Извлекает действительную составляющую этого числа.

изображение

Реферат. Извлекает мнимую составляющую этого числа.

абстрактный метод сопряженный ()

Реферат. Возвращает комплексное сопряжение. Например, (1+3j).conjugate() == (1-3j) .

класс номеров.Настоящий

К Complex , Real добавляет операции, которые работают с реальными числа.

Короче говоря, это: преобразование в float , math.trunc() , round() , math.floor() , math.ceil() , divmod() , //

, % , < , <= , > и >= .

Real также предоставляет значения по умолчанию для complex() , real , imag и conjugate() .

класс номеров.Rational

Подтипы Действительное и добавляет числитель и знаменатель свойств. Он также обеспечивает значение по умолчанию для с плавающей запятой() .

Числитель и знаменатель значений должны быть экземплярами Integral и должны быть в наименьших условиях с знаменатель положительный.

числитель

Реферат.

знаменатель

Реферат.

класс номеров. Интеграл

Subtypes Rational и добавляет преобразование в 9, | , ~ .

Примечания для разработчиков типа

Разработчики должны быть осторожны, чтобы сделать равные числа равными и хешировать их к одним и тем же значениям. Это может быть тонко, если есть два разных расширения действительных чисел. Например, дроби . Дробь реализует hash() следующим образом:

 по определению __hash__(я):
    если self.знаменатель == 1:
        # Получить целые числа правильно.
        хэш возврата (self. numerator)
    # Дорогая проверка, но точно правильная.
    если я == поплавок (я):
        вернуть хэш (с плавающей запятой (сам))
    еще:
        # Используйте хэш кортежа, чтобы избежать высокой частоты коллизий на
        # простые дроби.
        хеш возврата((self.numerator, self.denominator))
 

Добавление дополнительных числовых ABC

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

 класс MyFoo (комплекс): ...
MyFoo.register(Настоящий)
 

Реализация арифметических операций

Мы хотим реализовать арифметические операции так, чтобы смешанный режим операции либо вызывают реализацию, автор которой знал о типы обоих аргументов или преобразовать оба в ближайший встроенный тип и сделать операцию там. Для подтипов Интеграл , это означает, что __add__() и __radd__() должны быть определены как:

 класс MyIntegral(Integral):
    def __add__(я, другой):
        если isinstance (другое, MyIntegral):
            вернуть do_my_adding_stuff(я, другой)
        elif isinstance (другое, OtherTypeIKnowAbout):
            вернуть do_my_other_adding_stuff(я, другой)
        еще:
            вернуть нереализованный
    def __radd__(я, другой):
        если isinstance (другое, MyIntegral):
            вернуть do_my_adding_stuff(другое, себя)
        elif isinstance (другое, OtherTypeIKnowAbout):
            вернуть do_my_other_adding_stuff(другое, себя)
        elif isinstance (другой, интеграл):
            вернуть int(другое) + int(себя)
        elif isinstance (другое, реальное):
            вернуть поплавок (другой) + поплавок (сам)
        elif isinstance (другой, сложный):
            вернуть комплекс (другой) + комплекс (я)
        еще:
            вернуть нереализованный
 

Существует 5 различных случаев для операции смешанного типа над подклассами Комплекс . Я буду ссылаться на весь приведенный выше код, который не см. MyIntegral и OtherTypeIKnowAbout как «шаблон». a будет экземпляром A , который является подтипом Комплекс ( a : A <: Комплекс ) и b : B <: Комплекс . Я рассмотрю a + b :

  1. Если А определяет __add__() который принимает b , все хорошо.

  2. Если A возвращается к стандартному коду, вернуть значение из __add__() , мы бы упустили возможность что B определяет более интеллектуальный __radd__() , поэтому шаблон должен возвращать NotImplemented из __добавить__() . (Или может не реализовать __add__() в все.)

  3. Затем B __radd__() получает шанс. Если он принимает и , все хорошо.

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

  5. Если B <: A , Python пытается использовать B.__radd__ до А.__добавить__ . Это нормально, потому что это было реализовано с помощью знание A , поэтому он может обрабатывать эти экземпляры до делегирование Комплекс .

Если A <: Сложные и B <: Действительное без обмена какими-либо другими знаниями, тогда подходящей общей операцией является операция, включающая встроенный в комплексе , и оба __radd__() приземляются там, поэтому a+b == б+а .

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

 по определению _operator_fallbacks (мономорфный_оператор, резервный_оператор):
    защита вперед (а, б):
        если isinstance(b, (int, Fraction)):
            вернуть monomorphic_operator(a, b)
        elif isinstance(b, float):
            вернуть fallback_operator (с плавающей запятой (а), б)
        elif isinstance (b, комплекс):
            вернуть fallback_operator (комплекс (а), б)
        еще:
            вернуть нереализованный
    forward.__name__ = '__' + fallback_operator.__name__ + '__'
    вперед.__doc__ = мономорфный_оператор.__doc__
    деф реверс(б, а):
        если isinstance(a, Rational):
            # Включает целые числа.
            вернуть monomorphic_operator(a, b)
        elif isinstance(a, Real):
            return fallback_operator (с плавающей запятой (a), с плавающей запятой (b))
        elif isinstance(a, Комплекс):
            return fallback_operator (комплекс (а), комплекс (б))
        еще:
            вернуть нереализованный
    reverse. __name__ = '__r' + резервный_оператор.__name__ + '__'
    reverse.__doc__ = monomorphic_operator.__doc__
    возврат вперед, назад
определение _add (а, б):
    """а + б"""
    return Fraction (a.числитель * b.знаменатель +
                    б.числитель * а.знаменатель,
                    а.знаменатель * б.знаменатель)
__add__, __radd__ = _operator_fallbacks(_add, operator.add)
# ...
 

Python Numbers — неофициальная документация по разработке Python (заметки Виктора)

  • float : число с плавающей запятой, обычно IEEE 754 (64 бита, основание 2)
  • сложный : комплексный номер, реализованный как два числа с плавающей запятой
  • decimal.Decimal : число с плавающей запятой, хранящееся в базе 10, произвольное точность
  • дроби.Дробь : рациональная, числитель/знаменатель; автоматически вычислить наибольший общий делитель (НОД), чтобы упростить дробь
  • Числовая башня

    Модуль чисел определяется PEP 3141 — Иерархия типов для чисел.

    • номера.Номер: базовый класс
    • числа. Комплекс: добавить реальных , изображений , сопряженных ()
    • номера. Real: подкласс Complex; добавить много операций с плавающей запятой.
    • номера. Rational: подкласс Real; добавить числитель и знаменатель атрибуты
    • номера. Интеграл: подкласс Rational

    Подклассы:

    • числа.Числа: целочисленные, с плавающей запятой, комплексные, десятичные.Десятичные, дробные.Дробь
    • чисел. Комплекс: целое, число с плавающей запятой, комплекс, дроби. Дробь
    • числа. Вещественное число: целое число, число с плавающей запятой, дроби. Дробь
    • числа. Рациональное: целое, дроби. Дробь
    • числа. Интеграл: int

    int, float, сложные методы и атрибуты:

    • conjugate()
    • изображение
    • реальный

    Атрибуты целого числа и дроби:

    • знаменатель
    • числитель

    Преобразования в Python

    int(obj) и float(obj) accept:

    • int
    • поплавок
    • десятичный. Десятичный
    • дроби.Дробь
    • байт
    • ул

    int(obj) округляет до нуля (ROUND_DOWN, например: int(0.9) == 0 и int(-0.9) == 0 ).

    Но int(obj) и float(obj) reject:

    • комплекс

    комплекс(объект) принимает:

    • инт
    • поплавок
    • комплекс
    • десятичный. Десятичный
    • дроби. Фракция
    • ул

    Но комплекс(объект) отклоняет:

    • байт

    decimal.Decimal(obj) принимает:

    • int
    • поплавок
    • десятичный. Десятичный
    • ул

    Но decimal. Decimal(obj) отклоняет:

    • комплекс
    • дроби. Фракция
    • байт

    дроби. Фракция (объект) принимает:

    • целое число
    • поплавок
    • десятичный. Десятичный
    • дроби.Дробь
    • стр. (например: "1" или "1/2" )

    Но дроби. Фракция(объект) отбраковывает:

    • сложный
    • байт

    тип int

    Примеры:

     >>> (123).bit_length()
    7
    >>> sys.int_info
    sys.int_info (bits_per_digit = 30,
                 размер_цифры=4)
     

    Сериализация в байтах:

     >>> (123).to_bytes(4, 'маленький')
    б'{\х00\х00\х00'
    >>> int.from_bytes(b'{\x00\x00\x00', 'маленький')
    123
     

    Округление:

    • int(float) вызывает float. __trunc__() , поэтому округление до нуля (ОКРУГЛ_ВНИЗ)

    тип с плавающей запятой

    Примеры:

     >>> sys.float_info
    sys.float_info (макс. = 1,7976931348623157e+308,
                   макс_эксп = 1024,
                   max_10_exp=308,
                   мин=2,2250738585072014e-308,
                   мин_эксп = -1021,
                   min_10_exp=-307,
                   копать=15,
                   мант_коп = 53,
                   эпсилон=2,220446049250313e-16,
                   основание = 2,
                   раунды=1)
    >>> sys.float_repr_style
    'короткий'
    >>> (1.2).as_integer_ratio()
    (5404319552844595, 4503599627370496)
     

    Форматирование как шестнадцатеричное (основание 16):

     >>> (1.1).hex()
    '0x1.199999999999ap+0'
    >>> float.fromhex('0x1.199999999999ap+0')
    1.1
     

    Округление:

    • float.__trunc__(): Округление до нуля (ROUND_DOWN)
    • float.__round__(): Округлить до ближайшего, а ничьи — до ближайшего четного целого числа (ROUND_HALF_EVEN).
    • float.__int__() является псевдонимом для float.__trunc__() (ROUND_DOWN)

    Фракция

     >>> fractions.Fraction(5, 10) # int / int
    Фракция (1, 2)
    >>> Fraction.Fraction(1.2) # число с плавающей запятой
    Дробь(5404319552844595, 4503599627370496)
     

    C API

    Преобразование объекта Python в целое число. Методы типа:

    • __int__() : слот type->tp_as_number->nb_int
    • __index__() : тип слота ->tp_as_number->nb_index
    • __trunc__() (без слота)

    PyNumber_Long(obj) :

    • Вызов obj.__trunc__() (Округление до нуля, ROUND_DOWN)
    • или: если тип obj — bytes или str, анализировать строку в десятичном виде (с основанием 10)
    • или: ошибка!

    PyNumber_Index(x) вызывает метод __index__() : вызывает исключение, если тип не имеет метода __index__() или если метод не возвращает точно тип int (*).

    _PyLong_FromNbInt(x) :

    • Вызов type(x).__int__(x) : тип результата должен быть именно типом int (*)
    • или: ошибка!
    • Если тип (x) == int ( PyLong_CheckExact() )
    • вызов type(x).__index__(x) если определено: тип результата должен быть точно тип int (*)
    • вызов type(x).__int__(x) (вызов _PyLong_FromNbInt() ): тип результата должен быть точно типом int (*)
    • Ошибка
    • , если это не подкласс int и тип не определен __index__() ни __int__() метод
    • Новое в Python 3.8

    PyLong_AsLong() преобразует Python int в C long :

    • call _PyLong_FromNbIndexOrNbInt() 90 292
    • поднять OverflowError, если результат не помещается в C long
    • Python 3.7 и старше вызывают только __int__() , а не __index__() .

    PyLong_AsUnsignedLongMask() преобразует объект Python в беззнаковый C длинный :

    • вызов _PyLong_FromNbIndexOrNbInt(x) и затем _PyLong_AsUnsignedLongMask() на результат
    • Ошибка
    • , если объект не может быть преобразован в int с помощью _PyLong_FromNbIndexOrNbInt(x)
    • целочисленное переполнение маски
    • Python 3.7 и старше вызывают только __int__() , а не __index__() .

    (*) Особый случай: __int__() или __index__() возвращают подкласс int. Этот функция устарела, начиная с Python 3.3 (см. коммит 6a44f6ee). Эта функция может быть удалена из Python 3.9: см. bpo-17576.

    PyArg_ParseTuple и Py_BuildValue

    Справочная документация: разбор аргументов и построение значений.

    • PyArg_ParseTuple реализован в Python/getargs.c , основная функция: convertsimple() .

    • Py_BuildValue реализован в Python/modsupport.c , основная функция: do_mkvalue() .

    • Функции ведут себя по-разному, если определено PY_SSIZE_T_CLEAN :

      Для всех вариантов форматов # ( s# , y# и т.д.) тип файла аргумент длины (int или Py_ssize_t ) управляется определением макрос PY_SSIZE_T_CLEAN до включения Python.h .

    Форматы PyArg_ParseTuple:

    • "i" (C int ): __index__() или __int__() ; вызов PyLong_AsLong(obj) , но явно отклоняет float, используя PyFloat_Check(аргумент) .
    • "l" (C long ): __index__() или __int__() ; вызов PyLong_AsLong() , но явно отклоняет float, используя PyFloat_Check(arg)
    • "n" (C ssize_t ): __index__() ; вызов PyNumber_Index() и затем PyLong_AsSsize_t() . Исключение при переполнении.
    • "k" : вызовите PyLong_AsUnsignedLongMask() , если это подкласс int или int, ошибка иначе. Целочисленное переполнение маски .

    Примечание. В Python 3.7 и более ранних версиях PyLong_AsLong() вызывает только __int__() , не __index__() .

    Скрипт для обновления этой страницы

    number_tower.py:

     из __future__ import print_function
    импортировать номера
    предупреждения об импорте
    импортные фракции
    импортировать десятичный
    warnings.simplefilter("ошибка", DeprecationWarning)
    ЗНАЧЕНИЯ = (
     ("целое", 123),
     ("с плавающей запятой", 1,5),
     («сложный», сложный (0, 1,5)),
     ("десятичный.Десятичный", десятичный.Десятичный("1.1")),
     ("дроби.Дробь", дроби.Дробь(1, 7)),
     ("байты", б"123"),
     ("ул", "123"),
    )
    ТИПЫ = (
     ("целое", целое),
     ("плавать", плавать),
     ("сложный", сложный),
     ("десятичный.Десятичный", десятичный. Десятичный),
     ("дроби.Дробь", дроби.Дробь),
    )
    для type_descr, num_type в TYPES:
     принято = []
     отклонено = []
     для value_descr, значение в VALUES:
     пытаться:
     num_type(значение)
     кроме TypeError:
     отклонено.append(value_descr)
     еще:
     принято .append (value_descr)
     если принято:
     print("``%s(obj)`` accept:" % type_descr)
     Распечатать()
     для имени принято:
     print("* ``%s``" % имя)
     Распечатать()
     если отклонено:
     print("``%s(obj)`` отклонить:" % type_descr)
     Распечатать()
     для имени в отклоненном:
     print("* ``%s``" % имя)
     Распечатать()
    Распечатать()
    для имя_башни, тип_башни в (
     ("Число", цифры.Число),
     ("Комплекс", номера.Комплекс),
     ("Настоящий", цифры.Настоящий),
     («Рациональное», числа.Рациональное),
     ("Интеграл", числа.Интеграл),
    ):
     подклассы = []
     для type_descr, num_type в TYPES:
     если issubclass (num_type, tower_type):
     подклассы.
    Оставить комментарий

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

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