Как сравнивать числа в питоне

от admin

Условия (if, else, elif) и операторы сравнения

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

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

Функции input() можно передать в качестве аргумента строку, которую увидит пользователь перед вводом.

Как видно из примера, что-то пошло не так. Вместо заветных 46 после сложения 12 и 34 мы получили 1234. Все дело в типах данных. Функция input() всегда считывает данные в виде строки. Так и в примере она считала 12 и 34 как 2 строки и просто «слепила» их вместе. Мы же хотим складывать числа. Чтобы все работало хорошо, нужно выполнить преобразование типов данных.

В данном случае можно сделать вот так:

То, чего мы и хотели.

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

В примерах мы используем функцию type() . Как должно быть понятно из её названия, она выясняет тип переменной. Возвращает она что-то страшное вида <class ‘str’> . Сейчас не стоит вникать почему так. Нам важно, что преобразование прошло правильно и получился тип str .

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

Почему нужно конвертировать строки в числа

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

Вы удовлетворитесь ответом и пойдете домой. Но потом выяснится, что если ввести другие 2 числа, то все сломается:

Значит, не все так просто…

Чтобы разобраться в вопросе, нужно знать как сравниваются строки.

Компьютер умеет работать только с одним типом данных — числами. Мы же помимо чисел используем кучу разных типов данных: числа, строки, списки, словари, кортежи (последние 3 будут обсуждаться дальше в курсе). Оказывается, что и они все хранятся и обрабатываются компьютером в виде чисел. Разберемся со строчками.

Когда люди задумались, как можно обрабатывать строки, им прошла в голову простая идея — а давайте создадим единую таблицу, в которой каждому символу поставим в соответствие число. Так появилась таблица ASCII (American standard code for information interchange).

Когда люди стали пользоваться компютером не только в Америке (точнее говоря, не только в англоговорящих странах), то встал вопрос о том, что в таблице не хватает места. Так появились другие таблицы кодировок:

Python версии 3 использует Unicode — кодировку, которая на данный момент включает в себя знаки почти всех письменных языков мира. Emoji в ней, кстати, тоже есть ��������‍����

При сравнении строк, Python переводит все символы строки в числа и производит сравнение чисел.

Если перевести “числовые” строки из примеров выше в списки чисел, то получится:

  • ’12’ = [49, 50]
  • ’45’ = [52, 53]
  • ‘4’ = [52]
  • ’30’ = [51, 48]

Когда мы пишем ’12’ < ’45’ , то Python сравнивает числа обоих строк по очереди: 49 < 52 — True , значит строка ’12’ меньше, чем строка ’45’ .

Когда же мы пишем ‘4’ < ’30’ , то Python снова сравнивает числа обоих строк по очереди, но на этот раз получается иначе: 52 < 51 — False и ответ получается ‘4’ > ’30’ , что абсолютно верно с точки зрения сравнения строк, но абсолютный бред с точки зрения сравнения чисел.

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

Поэтому, если вы работаете с числами, то всегда работайте с ними как с числами, а не как со строками.

Условия

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

Теперь предположим, что мы хотим определить абсолютное значение любого числа. Наша программа должна будет напечатать сам x в случае, если он неотрицателен и -x в противном случае. Линейной структурой программы здесь не обойтись*, поэтому нам на помощь приходит инструкция if (если). Вот как это работает в питоне:

На самом деле в python есть функция abs() , с помощью которой можно взять модуль числа. Но в качестве примера использования конструкции if и так хорошо.

Разберем этот кусочек кода. После слова if указывается проверяемое условие (x > 0) , завершающееся двоеточием (это важно). После этого идет блок (последовательность) инструкций, который будет выполнен, если условие истинно. В нашем примере это вывод на экран величины x . Затем идет слово else (иначе), также завершающееся двоеточием (и это важно), и блок инструкций, который будет выполнен, если проверяемое условие неверно. В данном случае будет выведено значение -x .

Обратите особенное внимание на отступы во фрагменте кода выше. Дело в том, что в питоне, для того, чтобы определить, какой именно код выполнить в результате того или иного условия используется как знак двоеточия (в строке с самим условием), так и отступы от левого края строки.

Небольшая ремарка относительно табуляции. Мы используем 4 пробела! В современных текстовых редакторах при нажатии на tab автоматически вставляется 4 пробела. Не надо жать 4 раза кнопку space как вот тут. Никакой войны, никаких табов. Просто 4 пробела.

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

Таким образом, условные конструкции в питоне имеют следующий общий вид:

Вторая часть условной конструкции (та, что с else) может и отсутствовать, например так:

Эта программа тоже выведет абсолютное значение x, как и та, что была ранее.

Операторы сравнения

Все операторы сравнения в питоне достаточно интуитивны. Вот список основных:

> — больше. Условие истинно, если то, что слева от знака больше того, что справа.
< — меньше. Условие истинно, если то, что слева от знака меньше того, что справа.
>= — больше либо равно.
<= — меньше либо равно.
== — в точности равно.
!= — не равно.

Вложенные условные инструкции

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

Главное, не забывать отступы и двоеточия.

Тип данных bool

Операторы сравнения возвращают значения специального логического типа bool. Значения логического типа могут принимать одно из двух значений: True (истина) или False (ложь) .

Если преобразовать логическое True к типу int , то получится 1 , а преобразование False даст 0 . При обратном преобразовании число 0 преобразуется в False , а любое ненулевое число в True . При преобразовании str в bool пустая строка преобразовывается в False , а любая непустая строка в True .

Рассмотрим несколько примеров:

Обратите внимание, ключевые слова True или False пишутся с большой буквы. Если написать их с маленькой, то python подумает, что это переменная, попытается её найти и сломается, когда не найдет 🙁 . А если вы вздумаете называть свои переменные false или true , то сдать зачет по курсу вам не светит 🙂 . Учитесь сразу хорошему стилю программирования.

Логические операторы

Если мы хотим проверить два или более условий за раз, мы можем воспользоваться операторами and , or или not . Вот как они работают:

and (логическое И) возвращает истину ( True ) только в случае если оба условия по отдельности верны (тоже возвращают True )
or (логическое ИЛИ) вернет истину в случае, если хотя бы одно из условий верно.
not (логическое НЕТ) возьмет результат условия и “обратит” его. То есть, если результат условия True , то not примененный к этому условию вернет False и наоборот.

Давайте посмотрим как это работает на примере. Код ниже проверяет, что хотя бы одно число из двух нацело делится на 10 (кончается на 0) и если так, то печатает YES, а если нет, то печатает NO:

Пусть теперь мы хотим проверить, что числа a и b должны быть еще и обязательно больше нуля:

Как видите, мы можем не только использовать and и or в одном if , но и группировать условия скобками для того, чтобы явно обозначить приоритет вычисления условий.

Посмотрим пример с not . Пусть мы хотим проверить, что число a — положительное, а число b — неотрицательное. Это можно проверить вот таким условием:

Оператор pass очень полезен, когда нужно ничего не делать. Если его не поставить, то будет синтаксическая ошибка. А так, код считается правильным!

Кстати, not (b < 0) можно было бы и заменить на b >= 0 и код бы работал точно так же.

Конструкция elif

Иногда писать конструкции if-else долго и утомительно, особенно если приходится проверять много условий разом. В этом случае на помощь придет elif (сокращение от else if). По сути elif позволяет существенно упростить конструкцию ниже:

И сделать ее вот такой:

Обратите внимание, мы избавились от одного уровня вложенности. То есть, сам код стал более читаемым, но при этом нисколько не проиграл в функциональности. Разумеется, конструкции типа if-elif могут завершиться и блоком else , например так:

Задача: знак числа

В математике есть функция sgn, показывающая знак числа. Она определяется так: если число больше 0, то функция возвращает 1. Если число меньше нуля, то функция возвращает -1. Если число равно 0, то функция возвращает 0. Реализуйте данную функцию — для введенного числа выведите число, определяющее его знак. Используйте операторы сравнения и конструкцию if-elif-else .

Задача: високосный год

Дано натуральное число. Требуется определить, является ли год с данным номером високосным. Если год является високосным, то выведите YES, иначе выведите NO. Напомним, что в соответствии с григорианским календарем, год является високосным, если его номер кратен 4, но не кратен 100, а также если он кратен 400.

Ссылки по теме

Домашнее задание

Вам надо написать на питоне 6 программ, каждая из которых будет спрашивать у пользователя 3 числа (a, b, c) и печатать на экран удовлетворяют ли введенные числа перечисленным свойствам:

Операторы сравнения

Для сравнения двух величин в языке Python вводятся операции сравнения (отношения). Операции сравнения есть бинарные, то есть требуют двух операндов. Результатом любой операции сравнения есть логическое значение True или False . Значение True устанавливается, если операция сравнения выполняется (истина). Значение False устанавливается, если операция сравнения не выполняется (ложь).

Читать:
Build date is too old asus что делать

Чаще всего операции сравнения встречаются в операторах где происходит проверка условия ( if , while) и решение задачи зависит от выполнения или невыполнения некоторого условия.

Ниже приведен перечень операций сравнения в порядке убывания приоритета

  • == , != – операторы (операции) проверки на равенство (наивысший приоритет);
  • < , > , <= , >= – операторы сравнения соответственно меньше, больше, меньше или равно, больше или равно.
2. Примеры программного кода, который использует операции сравнения
3. Составные операции сравнения. Примеры

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

неявно превращается форму, в которой каждая операция представлена обычным образом но между соседними операциями используется оператор and

Операторы сравнения Python

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

Здесь может быть два возможных выхода: True или False .

Типы операторов сравнения в Python

Есть 6 типов операторов сравнения:

6 типов оператора сравнения

1. Меньше (<)

Он используется для проверки меньшего значения или переменной, содержащей меньшее значение по сравнению с другим числом или переменной. Если предоставленное число или переменная меньше указанного числа или переменной. Тогда оператор Less Than вернет True. В противном случае он вернет false.

2. Больше, чем (>)

Он используется для проверки большего значения или переменной, содержащей большее значение, по сравнению с другим числом или переменной. Если предоставленное число или переменная больше, чем данное число или переменная. Тогда оператор Greater Than вернет True. В противном случае он вернет false.

3. Равно (==)

Этот оператор проверяет одинаковые значения. Если введенное значение и данное значение равны, он вернет True, иначе False.

4. Не равно (! = Или <>)

Он обозначается != , Это полная противоположность оператору равенства. Он возвращает True, если значения по обе стороны от оператора не равны.

5. Меньше или равно (<=)

Этот оператор принимает значение True только если значение слева меньше или равно значению справа.

Вывод: b меньше или равно a

6. Больше или равно (> =)

Этот оператор принимает значение True только если значение слева больше или равно значению справа.

What is the best way to compare floats for almost-equality in Python?

It’s well known that comparing floats for equality is a little fiddly due to rounding and precision issues.

What is the recommended way to deal with this in Python?

Is a standard library function for this somewhere?

Peter Mortensen's user avatar

Gordon Wrigley's user avatar

18 Answers 18

If you’re using an earlier version of Python, the equivalent function is given in the documentation.

rel_tol is a relative tolerance, it is multiplied by the greater of the magnitudes of the two arguments; as the values get larger, so does the allowed difference between them while still considering them equal.

abs_tol is an absolute tolerance that is applied as-is in all cases. If the difference is less than either of those tolerances, the values are considered equal.

Something as simple as the following may be good enough:

Peter Mortensen's user avatar

I would agree that Gareth’s answer is probably most appropriate as a lightweight function/solution.

But I thought it would be helpful to note that if you are using NumPy or are considering it, there is a packaged function for this.

A little disclaimer though: installing NumPy can be a non-trivial experience depending on your platform.

Use Python’s decimal module, which provides the Decimal class.

From the comments:

It is worth noting that if you’re doing math-heavy work and you don’t absolutely need the precision from decimal, this can really bog things down. Floats are way, way faster to deal with, but imprecise. Decimals are extremely precise but slow.

math.isclose() has been added to Python 3.5 for that (source code). Here is a port of it to Python 2. It’s difference from one-liner of Mark Ransom is that it can handle "inf" and "-inf" properly.

I’m not aware of anything in the Python standard library (or elsewhere) that implements Dawson’s AlmostEqual2sComplement function. If that’s the sort of behaviour you want, you’ll have to implement it yourself. (In which case, rather than using Dawson’s clever bitwise hacks you’d probably do better to use more conventional tests of the form if abs(a-b) <= eps1*(abs(a)+abs(b)) + eps2 or similar. To get Dawson-like behaviour you might say something like if abs(a-b) <= eps*max(EPS,abs(a),abs(b)) for some small fixed EPS ; this isn’t exactly the same as Dawson, but it’s similar in spirit.

The common wisdom that floating-point numbers cannot be compared for equality is inaccurate. Floating-point numbers are no different from integers: If you evaluate «a == b», you will get true if they are identical numbers and false otherwise (with the understanding that two NaNs are of course not identical numbers).

The actual problem is this: If I have done some calculations and am not sure the two numbers I have to compare are exactly correct, then what? This problem is the same for floating-point as it is for integers. If you evaluate the integer expression «7/3*3», it will not compare equal to «7*3/3».

So suppose we asked «How do I compare integers for equality?» in such a situation. There is no single answer; what you should do depends on the specific situation, notably what sort of errors you have and what you want to achieve.

Here are some possible choices.

If you want to get a «true» result if the mathematically exact numbers would be equal, then you might try to use the properties of the calculations you perform to prove that you get the same errors in the two numbers. If that is feasible, and you compare two numbers that result from expressions that would give equal numbers if computed exactly, then you will get «true» from the comparison. Another approach is that you might analyze the properties of the calculations and prove that the error never exceeds a certain amount, perhaps an absolute amount or an amount relative to one of the inputs or one of the outputs. In that case, you can ask whether the two calculated numbers differ by at most that amount, and return «true» if they are within the interval. If you cannot prove an error bound, you might guess and hope for the best. One way of guessing is to evaluate many random samples and see what sort of distribution you get in the results.

Of course, since we only set the requirement that you get «true» if the mathematically exact results are equal, we left open the possibility that you get «true» even if they are unequal. (In fact, we can satisfy the requirement by always returning «true». This makes the calculation simple but is generally undesirable, so I will discuss improving the situation below.)

If you want to get a «false» result if the mathematically exact numbers would be unequal, you need to prove that your evaluation of the numbers yields different numbers if the mathematically exact numbers would be unequal. This may be impossible for practical purposes in many common situations. So let us consider an alternative.

A useful requirement might be that we get a «false» result if the mathematically exact numbers differ by more than a certain amount. For example, perhaps we are going to calculate where a ball thrown in a computer game traveled, and we want to know whether it struck a bat. In this case, we certainly want to get «true» if the ball strikes the bat, and we want to get «false» if the ball is far from the bat, and we can accept an incorrect «true» answer if the ball in a mathematically exact simulation missed the bat but is within a millimeter of hitting the bat. In that case, we need to prove (or guess/estimate) that our calculation of the ball’s position and the bat’s position have a combined error of at most one millimeter (for all positions of interest). This would allow us to always return «false» if the ball and bat are more than a millimeter apart, to return «true» if they touch, and to return «true» if they are close enough to be acceptable.

So, how you decide what to return when comparing floating-point numbers depends very much on your specific situation.

As to how you go about proving error bounds for calculations, that can be a complicated subject. Any floating-point implementation using the IEEE 754 standard in round-to-nearest mode returns the floating-point number nearest to the exact result for any basic operation (notably multiplication, division, addition, subtraction, square root). (In case of tie, round so the low bit is even.) (Be particularly careful about square root and division; your language implementation might use methods that do not conform to IEEE 754 for those.) Because of this requirement, we know the error in a single result is at most 1/2 of the value of the least significant bit. (If it were more, the rounding would have gone to a different number that is within 1/2 the value.)

Going on from there gets substantially more complicated; the next step is performing an operation where one of the inputs already has some error. For simple expressions, these errors can be followed through the calculations to reach a bound on the final error. In practice, this is only done in a few situations, such as working on a high-quality mathematics library. And, of course, you need precise control over exactly which operations are performed. High-level languages often give the compiler a lot of slack, so you might not know in which order operations are performed.

There is much more that could be (and is) written about this topic, but I have to stop there. In summary, the answer is: There is no library routine for this comparison because there is no single solution that fits most needs that is worth putting into a library routine. (If comparing with a relative or absolute error interval suffices for you, you can do it simply without a library routine.)

Похожие статьи