Я очень давно ничего не программировал алгоритмического, тем более на «правильных» языках, а тут подвернулся очень хороший повод заняться этим. На учебе, чтобы получить зачет, предлагали различные интересные задачки по желанию. Ну я естественно вызвался — досталась задача написать калькулятор, поддерживающий вычисления выражения, типа «2+3/4*2». Т.е. на входе дается выражение, состоящие из целых чисел, знаков «+, -, *, /» и нужно вычислить результат этого.
Первой мыслью было проходиться по входными символам, определять знаки и расставлять приоритет, хотел было уже так писать, но что-то меня остановило — решил погуглить, ведь задача с виду была довольно тривиальной. Результатом поисков стал алгоритм Бауэра и Замельзона. Который как раз умел делать с выражением то, что мне нужно. Было решено использовать его.
В качестве языка был выбран C#, как наиболее мне близкий из «правильных» языков (php я за такой не считаю). Первая версия, появившаяся уже после нескольких часов после получения задания, была довольно неуклюжей с точки зрения чистоты кода. Но уже она имела кое-какие улучшения по сравнению с первоначальным заданиям — поддерживались дробные числа и унарный минус. После того как отловил все ошибки я взялся за рефакторинг. После него код много стал много читабельней, ну и его стало просто меньше ;).
Следующим этапом довода кода до ума — стало написание тестов, сделано конечно не очень правильно(надо было сначала писать тесты), но уж лучше так, чем со всем без них. После написания тестов вносить изменения в код стало гораздо проще, и я интереса ради добавил реализацию возведения в степень.
Сегодня сдавал калькулятор. После беглого просмотра кода преподавателем, было задано задание дописать возведение в степень, но как вы помните — я ее уже реализовал ;). Тогда стали тестировать, как оно работает. Попалось выражение «2^3^2», угадайте, что выдал мой калькулятор? Правильно, выдал он 64. Но! преподаватель ожидал увидеть результат, аналогичный «2^(3^2)», я не очень силен в математике и не уверен в правильность такого приоритета, но надо было править… Алгоритм содержит хитрую таблицу переходу к нужной функции в зависимости от текущего символа и оператора, находящегося на вершине стека. Реализую степень, я взял данные с операций умножения и деления. Чтобы заставить вычислять степень по-новому, мне пришлось изменить всего один символ в программе
После этого пошел показывать программу опять, с этим выражением он справился на «ура»(кстати, эксель считал степень также как и мой калькулятор;)), но преподавателю опять удалось загнать калькулятор в тупик выражением «1+2^3^4*5»…Не описывая подробностей, скажу лишь, что для правки этого бага пришлось править целых два символа ;).
Зачет получен, ура! Но на пары ходить все равно буду, ибо интересно :).
Comments are closed, but trackbacks and pingbacks are open.