Что такое вещественные числа в python

Числа в Python

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

Целые числа

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

Вещественные числа

Для того чтобы записать действительное число в Python есть числа с плавающей точкой. Работая в программе с подобными величинами, можно получать более точные данные при арифметических подсчетах. Чтобы инициализировать объект, который содержит вещественное число, необходимо присвоить ему значение, где целая и дробная части разделены символом точки. В данном примере показано создание переменной f:

Комплексные числа

В языке программирования Python также поддерживается работа с комплексными числами. Подобная информация представлена в виде пары значений: действительной и мнимой части, которые разделяются символом операции сложения. Также в завершении мнимой составной части комплексного числа обязательно должна стоять буква j. В следующем фрагменте кода демонстрируется создание комплексной переменной c и выводится вся информация о ней:

Можно получить действительную и мнимую часть чисел отдельно. Для этого следует использовать real и image:

Системы счисления

Помимо общепринятой десятичной системы счисления, Python поддерживает приведение цифровых данных к двоичному, восьмеричному и шестнадцатеричному представлению. Чтобы начать работать с подобными числами, необходимо инициализировать переменные при помощи констант, обладающих префиксами 0b, 0o и 0x соответственно выбранному типу. В программе ниже создаются и выводятся на экран данные в различных системах:

Приведение типов

Используя стандартные средства языка Python, можно достаточно легко менять типовую принадлежность практически любой переменной. Для этого существуют методы, такие как int, float, complex, bin, oct, hex. Три последние функции позволяют перевести число либо переменную в десятичную, восьмеричную и шестнадцатеричную систему соответственно. Следующий фрагмент кода демонстрирует работу всех шести вышеописанных методов:

Операции над числами

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

ОперацияНазначение
a + bСложение a и b
a – bРазница между a и b
a * bУмножение a на b
a / bДеление a на b
a % bОстаток от деления a на b
a // bЦелая часть от деления a и b
a ** bВозведение a в степень b

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

a

ОперацияНазначение
a & bПобитовое И для a и b
a | bПобитовое ИЛИ для a и b
a ^ bИсключающее ИЛИ для a и b
Инверсия битов для a
a > bПобитовый сдвиг вправо для a на b
МетодНазначение
sqrt(a)Квадратный корень из a
log(a)Натуральный логарифм из a
fabs(a)Возвращает модуль a
round(a)Округляет a до ближайшего целого
round(a, b)Округляет a до b знаков после точки
floor(a)Округляет a до меньшего целого значения
ceil(a)Округляет a до большего целого значения
isfinite(a)Проверяет, является ли a числом
modf(a)Возвращает целую и дробную части a
sin(a)Синус угла a, указанного в радианах
cos(a)Косинус угла a, указанного в радианах
tan(a)Тангенс угла a, указанного в радианах

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

Ввод числа с клавиатуры

Для того чтобы получить числовые данные от пользователя используется стандартный метод input. Его вызов позволяет получать ввод информации с клавиатуры, который выполняется во время запуска программы на компьютере. В качестве аргумента для этого метода можно использовать строку, предлагающую пользователю ввести числовые сведения. Ниже показан пример того, как ввести в Pyhon с клавиатуры число. Переменная n получает значение и отображается на экране с помощью print:

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

Получить максимальное значение целочисленной переменной, которое поддерживается в текущей версии языка Python можно с помощью переменной sys.maxsize. Как правило, на разных компьютерах это число совпадать не будет из-за разной архитектуры процессоров. На данный момент из Python были убраны любые ограничения, касающиеся размерности вводимых величин. Вывести на экран максимальное число в Python можно следующим образом:

Заключение

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

Источник

Числа: целые, вещественные, комплексные

Числа в Python 3: целые, вещественные, комплексные. Работа с числами и операции над ними.

Целые числа (int)

Числа в Python 3 ничем не отличаются от обычных чисел. Они поддерживают набор самых обычных математических операций:

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

Битовые операции

Над целыми числами также можно производить битовые операции

Дополнительные методы

Системы счисления

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

Вещественные числа (float)

Вещественные числа поддерживают те же операции, что и целые. Однако (из-за представления чисел в компьютере) вещественные числа неточны, и это может привести к ошибкам:

Для высокой точности используют другие объекты (например Decimal и Fraction)).

Также вещественные числа не поддерживают длинную арифметику:

Простенькие примеры работы с числами:

Дополнительные методы

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

Модуль math предоставляет более сложные математические функции.

Модуль random реализует генератор случайных чисел и функции случайного выбора.

Комплексные числа (complex)

В Python встроены также и комплексные числа:

Для работы с комплексными числами используется также модуль cmath.

Источник

Вещественные числа — float

Другой отличительной чертой является необязательное наличие символа » e » – экспоненты:

Если на длину целых чисел не накладывается абсолютно никаких ограничений по величине, то с вещественными числами это не так. Что бы узнать информацию о числах типа float для компьютера на котором выполняется программа, можно воспользоваться командой sys.float_info :

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

Арифметические операции

Целые числа поддерживают следующие математические операции, которые отсортированы по убыванию приоритета:

Важно: приоритет математических операций выше побитовых логических операций и операций сравнения.

I. возведение \(0\) в степень \(0\) возвращает \(1\):

Извлечение корней четной степени из отрицательных чисел не вызывает ошибки, а возвращает комплексное число:

Использование в выражении x ** y слишком больших значений x и y типа float может привести к ошибке OverflowError.

IV. встроенная функция int() отбрасывает дробную часть вещественных чисел:

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

Операции сравнения

Для сравнения чисел, доступно \(8\) операций сравнения, причем все они имеют одинаковый приоритет:

Важно: приоритет операций сравнения ниже математических и побитовых операций.

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

В Python сравнение x > y and y > z является эквивалентным x > y > z т.е. сравнения связаные оператором and в произвольные цепочки могут быть записаны в более компактной форме. Выполнение таких выражений начинается слева направо и останавливается как только будет получено первое значение False. Это означает, что если в выражении x > y > z сравнение x > y вернет False то сравнение y > z выполняться не будет.

Методы вещественных чисел

Вещественные числа – это объекты, которые обладают следующими методами:

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

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

Показатель степени ‘p’ exponent является степенью двойки, например, перевод числа ‘0x2.f1ap+3’ из шестнадцатеричной системы счисления в десятичную будет выглядеть следующим образом:

Применение обратного преобразования дает другую шестнадцатеричную строку, которая, однако, представляет тоже самое число:

Источник

Числа в Python (FAQ)

Ч исла в Python (как и в других языках программирования) чрезвычайно простое понятие. В Python все переменные представляют собой объекты и размещаются в динамической памяти.

Базовый набор Python содержит следующие типы чисел:

Целые числа (int)

Любое целое число состоит из массива цифр переменной длины, поэтому в Python 3 в переменную типа int может быть записано число неограниченной длины. Единственное ограничение длины — это размер оперативной памяти.

>>> 134523345234252523523478777 ** 2 18096530413013891133013347014216107772438771969415729

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

Вещественные числа (float)

Числа типа float — неточны (из-за представления чисел с плавающей запятой в компьютере).

>>> 0.3 + 0.3 + 0.3 + 0.1 0.9999999999999999

Информацию о точности и внутреннем представлении float для вашей системы можно получить из sys.float_info

>>> import sys >>> sys.float_info sys.float_info(max=1.7976931348623157e+308, max_exp=1024, max_10_exp=308, min=2.2250738585072014e-308, min_exp=-1021, min_10_exp=-307, dig=15, mant_dig=53, epsilon=2.220446049250313e-16, radix=2, rounds=1)

Если нужна высокая точность обычно используют модули Decimal и Fraction.

Комплексные числа (complex)

Отдельные части комплексного числа доступны через атрибуты real и imag

>>> num = 1.1+2j >>> num.real, num.imag (1.1, 2.0)

Операции с числами

Является ли переменная числом

Любую переменную можно проверить на тип (int, float или complex):

n = 10 >>> if type(n) == int: print(«This is int») This is int

Если вы хотите проверить, находится ли в строке число, воспользуйтесь методом isdigit()

>>> string = «404» >>> string.isdigit() True

Однако стоит помнить, что метод isdigit() не работает для отрицательных чисел и чисел с плавающей точкой.

Также для проверки на число, можно написать собственную функцию:

>>> def isInt(value): try: int(value) return True except ValueError: return False >>> isInt(123) True >>> isInt(«qwerty») False >>> isInt(«123») True >>> isInt(«-123») True >>> isInt(«123.2») False

Арифметические операции

Сравнение чисел

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

Ввод чисел

Если нужен список чисел, введите несколько чисел через пробел и выполните:

my_list = [int(x) for x in input().split()] print(my_list) > [1, 2, 3]

Вывод чисел

Для вывода числа используйте print() :

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

>>> print(«int variable = » + str(1)) int variable = 1 >>> print(«int variable = <>«.format(1)) int variable = 1 >>> print(f’int variable = <1>‘) # f-строки работаюв в Python 3.6+ int variable = 1

Источник

2.6. Вещественные числа¶

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

На самом деле эта тема неожиданно сложная. Постарайтесь понять всё, что написано в этом разделе, но если что-то не поймете по началу, это не страшно. Главное — два правила работы с вещественными числами, которые я напишу ниже.

2.6.1. Запись чисел с плавающей точкой¶

Вы точно знаете, что вещественные числа можно записывать в виде «12.34» — это «двенадцать целых тридцать четыре сотых».

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

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

При записи чисел с плавающей точкой запись имеет следующий вид: 1.234e1. Она состоит из двух частей, разделенных английской буквой e (может использоваться как маленькая, так и заглавная буква, хотя сейчас вроде чаще используют маленькую). Такая запись обозначает: «возьми число 1.234 и сдвинь в нем точку на 1 позицию направо» — соответственно, получается то же 12.34. Аналогично, возможна запись 0.1234e2 — взять число 0.1234 и сдвинуть точку на две позиции направо, это будет то же 12.34. Число после e может быть быть нулем, это значит, что точку сдвигать не надо: 12.34e0 — это то же самое, что 12.34. Число может быть отрицательным, что значит, что точку надо сдвигать влево, а не вправо: 123.4e-1 или 1234e-2 — это все тоже 12.34. (Обратите внимание, что в записи 1234e-2 вообще отсутствует точка — она тогда, конечно, неявно подразумевается на конце записи числа 1234, точно так же, как 1234 и 1234.0 — это одно и то же.)

То есть еще раз: 0.1234e2, 1.234e1, 12.34e0, 12.34, 123.4e-1, 1234e-2, и даже 123400e-4 и 0.001234e4 — это все записи одного и того же числа 12.34. Записи разные, число одно и то же.

Видно, что одно и то же число можно записать разными способами. Чаще пишут так, чтобы либо перед точкой была ровно одна ненулевая цифра (1.234e1), или чтобы перед точкой был ноль, зато сразу после точки шла ненулевая цифра (0.1234e2), но в целом любая из приведенных в предыдущем абзаце записей является правильной, и есть много правильных записей, которые не приведены выше.

Еще примеры: 1.3703599907444e2 и 13703599907444e-11 — это 137.03599907444.

Запись чисел с плавающей точкой особенно удобна, когда вам надо хранить очень большие или очень маленькие числа. Например, расстояние от Земли до Солнца примерно 147 миллионов километров, т.е. 147000000000 метров. Так записывать очень неудобно, потому что надо тщательно считать нолики. Намного удобнее написать 147e9 — сразу понятно, что будет девять ноликов, и сразу понятно, что это 147 миллиардов. Или, например, атом водорода весит примерно 1.66e-24 грамм, т.е. 0.00000000000000000000000166 грамм (если я не ошибся в количестве ноликов 🙂 ). Ясно, что первая запись намного удобнее.

2.6.2. Как компьютер хранит вещественные числа¶

Вещественные числа, с которыми может иметь дело компьютер, могут быть как очень большими, так и очень маленькими. С другой стороны, вещественные числа в принципе невозможно хранить абсолютно точно, т.к. в них могут быть очень много знаков (даже бесконечно много) после точки.

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

Вообще, на самом деле компьютер хранит числа в двоичной системе счисления (т.е. на самом деле компьютер хранит не десятичную экспоненту, как это было описано выше, а двоичную), но это вам будет пока не особенно важно, потому что весь ввод-вывод вещественных чисел использует все-таки десятичную экспоненту.

2.6.3. Типы данных¶

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

Уточню, что значит «столько-то цифр мантиссы» и «такая-то экспонента». Как я писал выше, в мантиссе хранится только несколько первых цифр. Собственно, в single хранится только 7-8 цифр, в double 15-16, в expended 19-20. То есть например, если вы попытаетесь в single записать число 1.234567890123456789e20, то на самом деле запишется примерно 1.234567e20, остальные цифры будут отброшены. (На самом деле все немного сложнее из-за того, что числа хранятся в двоичной системе счисления, собственно поэтому я и пишу 7-8 цифр, потому что на самом деле как повезет в плане двоичной системы счисления.)

Ограничение же на экспоненту обозначает, что числа со слишком большой экспонентой вы просто не сможете записать в нужный тип (например, 1.23e100 не влезет в single), будет или ошибка, или получится специальное значение «бесконечность»; а числа со слишком большой отрицательной экспонентой просто будут считаться равными нулю (если вы попробуете записать 1.23e-100 в single, то получится 0).

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

К сожалению, конкретно в питоне нет простой возможности выбрать один из этих трех типов, можно работать только с double, причем в питоне вместо слова double используется название float (что вообще странно, потому что в других языках float — это single, а вовсе не double). Таким образом,

Стандартные вещественные числа в питоне называются float, хранят 15-16 цифр в мантиссе и экспоненту до примерно ±300.

2.6.4. Про «значащие цифры»¶

Как мы видели, одно и то же число можно записать с плавающей точкой по-разному. Чисто 12.34 можно записать как 0.0000000001234e11, и как 1234000000000e-11, и т.п. Конечно, компьютер будет хранить число каким-то конкретным образом. Более того, если, например, попробовать записать 0.0000000001234e11 например в single, то вы можете сказать, что будут записаны только нули (потому что мантисса хранит только 7-8 цифр).

На самом деле компьютер хранит числа чуть сложнее. В первом приближении можно считать, что компьютер хранит числа так, чтобы до точки была ровно одна ненулевая цифра (про это я писал выше), т.е. число 12.34 компьютер будет хранить как 1.234e-1 и никак иначе, а например расстояние от Земли до Солнца в метрах — как 1.47e11 и не иначе. (А на самом деле еще сложнее из-за двоичной системы счисления).

Поэтому компьютер никогда не будет хранить в мантиссе ведущих нулей. В этом смысле говорят о «значащих цифрах» — это цифры в записи числа, начиная с первой ненулевой цифры. Например, в числе 12.3405 значащие цифры — это 1, 2, 3, 4, 0, 5, а в числе 0.00000000000000000000000000166 значащие цифры — это 1, 6 и 6 (и компьютер будет хранить это число как 1.66e-27).

Поэтому говорят, что тип single хранит 7-8 значащих цифр, double — 15-16 значащих цифр, extended — 19-20.

2.6.5. Про дырки между числами¶

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

Из-за того, что компьютер хранит строго определенное количество значащих цифр, получается, что между соседними числами конкретного типа есть «дыры». Например, пусть мы возьмем тип single. В него невозможно записать число 1.2345678901234 — можно записать только 1.234567 или 1.234568. Получается, что между числами 1.234567 или 1.234568 есть целая «дыра» длиной 0.000001, в которой нет ни одного числа, которое может храниться в single.

Когда сами числа не очень большие, то и «дыры» не очень длинные. Но когда числа становятся большими, то и «дыры» тоже становятся больше. Например, число 123456789 тоже невозможно записать в single, можно записать только 123456700 или 123456800 — «дыра» получается уже длины 100!

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

2.6.6. Базовые операции¶

С вещественными числами доступны все привычные уже вам операции: +-*/, abs, sqrt, ввод-вывод через float(input()), map(float, …) и print. Также работает деление с остатком (// и %).

2.6.7. Про вывод подробнее¶

Часто в наших задачах вы можете встретить фразу «выведите ответ с точностью до 5 знаков после запятой», или «с пятью верными знаками» и т.п. Такие фразы почти всегда обозначают, что ваш ответ должен содержать 5 верных цифр после запятой, но они не запрещают вам выводить больше цифр. Вы можете вывести хоть 20 цифр — если первые пять из них верные, то ответ будет зачтен. И наоборот, вы можете вывести меньше цифр — если невыведенные цифры — нули, то ответ тоже будет зачтен. Вообще, строго говоря, такая фраза в условии просто обозначает, что ваш ответ должен отличаться от верного не более чем на 1e-5.

Пример: если правильный ответ на задачу — 0.123456789, то вы можете вывести 0.12345, или 0.123459876, или даже 1.2345e-1 (т.к. это то же самое, что и 0.12345). А если правильный ответ — 0.10000023, то вы можете вывести 0.10000, 0.10000987 или даже просто 0.1 или 1e-001 (т.к. это то же самое, что и 0.10000).

В частности, это обозначает, что вы можете пользоваться стандартной функцией вывода (print) без каких-либо особых ухищрений; не надо округлять число, не надо форматировать вывод и т.д.

Вот если в задаче строго сказано «вывести ровно с 5 знаками после запятой», то это другое дело. Но на приличных олимпиадах такое бывает очень редко.

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

В питоне есть несколько функций, которые вам будут полезны при работе с вещественными числами. Для ряда из этих функций надо в самом начале программы написать from math import * (как вы уже писали для квадратного корня). Кроме того, имейте в виду, что с этими функциями также могут возникать проблемы погрешностей (см. ниже).

Пример программы, использующей эти функции:

2.6.9. Погрешности¶

2.6.9.1. Два правила работы с вещественными числами¶

Сначала напишу два главных правила работы с вещественными числами:

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

x | yПобитовое или
x ^ yПобитовое исключающее или
x & yПобитовое и
x > yБитовый сдвиг вправо
[1](1, 2) за исключением случаев, когда вам не важно, что произойдет в случае точного равенства, см. ниже

Ниже я разъясняю оба этих правила.

2.6.9.2. Необходимость использования eps ¶

Как уже говорилось выше, компьютер не может хранить все цифры числа, он хранит только несколько первых значащих цифр. Поэтому, если, например, разделить 1 на 3, то получится не 0.33333… (бесконечно много цифр), а, например, 0.33333333 (только несколько первых цифр). Если потом умножить результат обратно на 3, то получится не ровно 1, а 0.99999999. (Аналогичный эффект есть на простых калькуляторах; на продвинутых калькуляторах он тоже есть, но проявляется сложнее.)

(Вы можете попробовать потестировать, правда ли, что (1/3)*3 равно 1, и обнаружить, что проверка if (1 / 3) * 3 == 1 выполняется. Да, тут повезло — опять-таки из-за двоичной системы получилось округление в правильную сторону. Но с другими числами это может не пройти, например, проверка if (1 / 49) * 49 == 1 не срабатывает.)

На самом деле все еще хуже: компьютер работает в двоичной системе счисления, поэтому даже числа, в которых в десятичной системе счисления имеют конечное число цифр, в компьютере могут представляться неточно. Поэтому, например, сравнение if 0.3 + 0.6 == 0.9 тоже не сработает: если сложить 0.3 и 0.6, то получится не ровно 0.9, а слегка отличающее число (0.899999 или 0.900001 и т.п.)

Действительно, напишите и запустите следующую программу:

и вы увидите, что она выводит Fail.

(Более того, print(0.3+0.6) выводит у меня 0.8999999999999999.)

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

Итак, именно поэтому получаем

(Первое правило будет дальше 🙂 )

2.6.9.3. Выбор eps ¶

(И вообще, конечно, вариантов много — подошло бы любое число, которое существенно меньше 1e-3 и существенно больше 1e-12. Вот это и есть «хорошая» ситуация, когда варианты «равны» и «не равны» разделены очень сильно. А если бы они не были бы так разделены, то весь фокус с eps не прошел бы. Это то, про что я писал немного выше.).

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

И поэтому получаем

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

2.6.10. Дополнительный материал. «Грубые» задачи: когда eps не нужно¶

Здесь мы сравниваем два вещественных числа, чтобы найти максимум из них. Казалось бы, в соответствии со сказанным выше, в сравнении нужен eps … но нет! Ведь если два числа на самом деле равны, то нам все равно, в какую из веток if мы попадем — обе ветки будут верными! Поэтому eps тут не нужен.

Так иногда бывает — когда вам все равно, в какую ветку if’а вы попадете, если два сравниваемых числа на самом деле равны между собой. В таком случае eps использовать не надо. Но каждый раз тщательно думайте: а правда ли все равно? Всегда лучше перестраховаться и написать eps (выше с eps тоже все работало бы), за исключением совсем уж простых случаев типа приведенного выше вычисления максимума.

Еще пример: считаем сумму положительных элементов массива

Еще пример, где уже eps необходим: определим, какое из двух чисел больше:

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

Тогда в задаче (фрагменте кода) eps нужен, если задача является негрубой: тогда существуют такие входные данные, которые вам важно отличить от очень близких им. Например, если надо определить, какое из двух чисел больше, то при входных данных «0.3 0.3» надо ответить «они равны», но при очень небольшом изменении входных данных, например, на «0.300001 0.3» ответ резко меняется: надо отвечать «первое больше».

Если же задача (или фрагмент кода) является грубым, то, скорее всего, в нем можно обойтись без eps : если вы чуть-чуть ошибетесь при вычислениях, ответ тоже изменится не очень сильно. Например, если вы вычисляете максимум из двух чисел, то на входных данных «0.3 0.3» ответ 0.3, а на входных данных «0.300001 0.3» ответ 0.300001, т.е. изменился не очень сильно.

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

2.6.11. Примеры решения задач¶

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

Маша наблюдает из дома за грозой. Она увидела молнию, а через \(T\) секунд услышала гром от молнии. Она знает, что в той стороне, где была молния, есть одинокое дерево, и боится, не попала ли молния в это дерево. Расстояние от Машиного дома до дерева равно \(L\) метров, скорость звука равна \(V\) метров в секунду, скорость света считаем бесконечной. Определите, могла ли молния попасть в дерево.

Пример:

Итоговый код получается такой:

Выбор eps тут в существенной мере произвольный, подробнее про выбор eps описано выше в основной части теории.

Пример:

Источник

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

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