{ "cells": [ { "cell_type": "markdown", "source": [ "#Калькулятор на Stepik'у\n", "\n" ], "metadata": {} }, { "cell_type": "markdown", "source": [ "Напишите простой калькулятор, который считывает с пользовательского ввода три строки: первое число, второе число и операцию, после чего применяет операцию к введённым числам (\"первое число\" \"операция\" \"второе число\") и выводит результат на экран.\n", "\n", "Поддерживаемые операции: `+, -, /, *, mod, pow, div`, где \n", "\n", "> mod — это взятие остатка от деления, \n", "\n", "> pow — возведение в степень, \n", "\n", "> div — целочисленное деление.\n", "\n", "Если выполняется деление и второе число равно 0, необходимо выводить строку `\"Деление на 0!\"`.\n", "\nОбратите внимание, что на вход программе приходят **вещественные числа**." ], "metadata": {} }, { "cell_type": "code", "source": [ "first = float(input())\n", "second = float(input())\n", "action = input()\n", "operations = {\"mod\": \"%\", \"div\": \"//\", \"pow\": \"**\"}\n", "try:\n", " print(eval(\"(\" + str(first) + \")\" + operations.get(action, action) + str(second)))\n", "except ZeroDivisionError:\n", " print('Деление на 0!')" ], "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "5\n", "0\n", "mod\n", "Деление на 0!\n" ] } ], "execution_count": 1, "metadata": {} }, { "cell_type": "markdown", "source": [ "Нашел интересный вопрос Льва Романова: _\"нельзя как-то заставить питон считать операцию инпута?_ например `s = a + c + b`, где «`с`» это операция?\" - да, можно (правда в предыдущих уроках почти ничего из этого не было)\n", "\n", "Всё довольно просто - на вход мы получаем три значения, два числа и знак, и, если их в правильном порядке соединить друг с другом, получится вполне осмысленное выражение.\n", "\n", "Для того, чтобы это выражение прочитать, есть функция `eval()`, принимающая на вход строку и преобразовывающая её в выражение, с которым интерпретатор может работать. Соответственно, нам необходимо все три значения привести к типу `string*` и объединить их в одну строку, что легко сделать при помощи конкатенации строк.\n", "\n", "Если со знаками `+, -, *, /` всё просто, их интерпретатор воспримет как надо и выдаст корректный результат, то как быть с `pow, div, mod`, ведь таких действий питон не знает. Нужно им как-то задать соответствия и в этом помогает словарь. В словаре задаются пары ключ, значение. В моём решении это переменная operations. Получить значение по ключу можно несколькими способами, но, так как я в словаре указал всего три пары, мне был нужен тот, который избавит меня от лишней условной инструкции, указывающей интерпретатору что делать, если ключа нет в словаре. Это метод `.get()`. Он позволяет получить из словаря значение по ключу, так же в нём можно указать значение, которое будет возвращаться в случае отсутствия указанного ключа в словаре. Выглядит это следующим образом `словарь.get(\"ключ\", \"значение, если ключа нет в словаре\")`.\n", "\n", "Осталось лишь обработать ситуацию, когда что-то делится на `0`. Тут можно было бы использовать условную инструкцию, перечислить условия, когда выдавалось бы сообщение `\"Деление на 0!\"`, но это было бы более громоздко и, на мой взгляд, менее читабельно. Потому я использовал `try...except`. Эта конструкция пробует выполнить действие указанное в блоке `try` и, если возникает ошибка, указанная в `except` (в нашем случае это `ZeroDivisionError`, тоесть деление на 0) действие программы не прерывается, а выполняется блок except, в нашем случае это печать сообщения \"Деление на 0!\".\n", "\n* А вообще, чтобы не совершать лишних преобразований, можно было бы все три переменные считать как `input()`, тогда они будут строками, и не преобразовывать из типа `float` обратно в тип `string`, но я об этом поздно подумал" ], "metadata": {} }, { "cell_type": "code", "source": [ "a, b, op = input(), input(), input()\n", "print (\"Деление на 0!\" if op in (\"/\", \"div\", \"mod\") and float(b) == 0 else eval(\"({0}){1}\".format(a, {'pow':'**', 'div':'//', 'mod':'%'}.get(op, op) + b)))\n", "\n", "# Калькулятор в два рядки :-)\n", "# перевіряє тільки вказану помилку." ], "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "6\n", "0\n", "/\n", "Деление на 0!\n" ] } ], "execution_count": 5, "metadata": {} }, { "cell_type": "code", "source": [ "# з exec але аж в 4 рядки\n", "\n", "try:\n", " exec('print(({0}){2}{1})'.format(input(),input(),input()).replace('mod','%').replace('div','//').replace('pow','**'))\n", "except(Exception):\n", " print('Деление на 0!')" ], "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "8\n", "4\n", "pow\n", "4096\n" ] } ], "execution_count": 6, "metadata": {} }, { "cell_type": "code", "source": [ "# Ще один подібний\n", "\n", "import operator\n", "a,b,c = (input() for _ in range(3))\n", "o = {'+' : operator.add, '-' : operator.sub,'*' : operator.mul,'/' : operator.truediv,'mod' : operator.mod,'pow' : operator.pow,'div' : operator.floordiv}\n", "try:\n", " exec(\"print(o[c](float(a),float(b)))\")\n", "except:\n", " print('Деление на 0!')" ], "outputs": [], "execution_count": null, "metadata": { "collapsed": true } }, { "cell_type": "code", "source": [ "# в один рядок з коментарями :-)\n", "exec(\"print(eval('(a) {} b'.format({'div': '//', 'mod': '%', 'pow':'**'}[o] if o in ['div','mod','pow'] else o))) if not(o in ['div','mod','/'] and float(b)==0) else print('Деление на 0!')\", {'a':float(input()),'b':float(input()),'o':input()})\n", "\n", "'''\n", "\n", "'''\n" ], "outputs": [], "execution_count": null, "metadata": { "collapsed": true } }, { "cell_type": "markdown", "source": [ "черт, ну кто-то же сделал 2.0! >E~~ гугл сходу на `complexity score` выдает pip-пакет radon, а тут им же считают? конечно все эти однострочные сверхбыстрые исполнения - та еще фаллометрия, и что-то мне подсказывает, что в боевых условиях за такие колбасы по рукам-то хорошенько настукивают. но и вправду хотелось бы почитать про оптимизации, внутреннюю организацию python, вот это вот все. так-то курс вообще легкий, если б не эти скоры - давно б уже закончил :-)\n", "\n\n", "[вот офф дока] (https://docs.python.org/3/reference/expressions.html#binary-arithmetic-operations)\n", "\n", ">и в ней в частности для `floor division` и `modulo` сказано: \n", ">>\"The numeric arguments are first converted to a common type.\"\n", "\n", ">а для `modulo` еще и особенно подчеркнуто как именно все прекрасно работает и с `floating point`.\n", "\n" ], "metadata": {} }, { "cell_type": "code", "source": [ "# Найшвидший\n", "\nexec(\"exec(\\\"print(eval('(a) {} b'.format({'div': '//', 'mod': '%', 'pow':'**'}[o] if o in ['div','mod','pow'] else o))) if not(o in ['div','mod','/'] and float(b)==0) else print('Деление на 0!')\\\", {'a':float(input()),'b':float(input()),'o':input()})\")" ], "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "8\n", "8\n", "*\n", "64.0\n" ] } ], "execution_count": 7, "metadata": {} }, { "cell_type": "code", "source": [ "# Це цікаве рішення\n", "a =float(input())\n", "b =float(input())\n", "c =str(input())\n", "\n\n", "if (c=='mod' or c=='div' or c=='/') and b == 0:\n", " print('Деление на 0!')\n", " \n", "elif c==('mod'):\n", " print(a%b)\n", " \n", "elif c==('div'):\n", " print(a//b)\n", " \n", "# але як калькулятор не працює :-)\n", "# тільки заявлені в задачі оператори" ], "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "5\n", "3\n", "+\n" ] } ], "execution_count": 2, "metadata": {} }, { "cell_type": "code", "source": [ "# Ще одне хороше рішення\n", "\n", "a, b, c = [input() for i in range(3)]\n", "print (\"Деление на 0!\" if c in (\"/\", \"div\", \"mod\") and float(b) == 0 else eval(\"({0}){1}\".format(a, {'pow':'**', 'div':'//', 'mod':'%'}.get(c, c) + b)))" ], "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "99\n", "88\n", "/\n", "1.125\n" ] } ], "execution_count": 8, "metadata": {} }, { "cell_type": "code", "source": [], "outputs": [], "execution_count": null, "metadata": { "collapsed": true } } ], "metadata": { "kernelspec": { "name": "python3", "language": "python", "display_name": "Python 3" }, "language_info": { "name": "python", "version": "3.6.3", "mimetype": "text/x-python", "codemirror_mode": { "name": "ipython", "version": 3 }, "pygments_lexer": "ipython3", "nbconvert_exporter": "python", "file_extension": ".py" }, "kernel_info": { "name": "python3" } }, "nbformat": 4, "nbformat_minor": 2 }