23.06.2022

Кулькулятор

Мартышка в старости слаба глазами стала...

Короче, приходится частенько пользоваться калькулятором. И с некоторых пор стандартный виндовый калькулятор стал мне мелковат.
Да честно говоря, всегда он немного раздражал совершенно непродуманным размещением кнопок. Видимо, это раздражения от привычки к советскому программируемому калькулятору МК-61. Вот так он выглядел.


И это я еще сижу на "семерке". На десятке там вообще не калькулятор, а "вырви глаз" какой-то. Доходит до того, что в сборках Windows 10 на торрентах включают калькулятор из семерки.
Кстати, на Android ситуация не лучше. У меня Xiaomi, инженерный режим на ихнем калькуляторе просто ужасен. Такое ощущение, что разработчики калькуляторов вообще ни разу не инженеры, поэтому интерфейс и подбор функций, мягко говоря, удивляет.

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

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

Видимо, здесь нужно было написать: "и при равенстве приоритетов op2 является левоассоциативным".

Интерфейс у моего калькулятора тоже не ахти, выглядит он вот так.

Ага, и с английским я тоже не очень-то дружу. Тем не менее, ссылочку на исполняемый файл оставлю, вдруг надо кому.

6 комментариев:

  1. Я не думаю что это ошибка, просто порядок операций в выражении из нескольких операций с равным приоритетом но разной ассоциативностью вроде не определен, скажем a + b = c +  d (+ - лево, а  = - правоассоциативно), можно интерпретировать как:
    - (a + (b = c)) + d - алгоритм из википедии
    - (a + b) = (c + d) - Ваша реализация

    ОтветитьУдалить
  2. Не совсем. В математике так, но там вроде и нет понятий левоассоциативная и правоассоциативная операций?
    В программировании же четко: при равенстве приоритетов у левоассоциативной операции сначала выполняются те операции, что слева, при правоассоциативной - те, что справа.
    В частности, операция присвоения - всегда правоассоциативна.
    В принципе, большинство операций вполне себе левоассоциативны, но вот хитрость есть с операцией возведения в степень, которую всегда удобнее считать правоассоциативной. В частности, 2^3^4 чему равна? При записи на бумаге, очевидно, что это будет записано в виде лесенки, поэтому сначала 3^4 = 81, а уже потом только 2^81, но не 8^4.

    Кстати, многие студенты при вычисления на калькуляторе ошибаются при расчетах обыкновенной дроби, записанной с горизонтальной чертой. Например 2*3/5*7 они вычисляют прямо в таком порядке, ведь операции деления и умножения имеют один приоритет? И в результате получают неверный результат. Ошибка в том, в что в дроби с горизонтальной чертой фактически знаменатель заключен в скобки. То есть правильно было бы так 2*3/(5*7).
    Я ради эксперимента поменял ассоциативность у операции деления. В результате первый пример посчитался правильно, но если в знаменателе заменить умножение на деление, то есть 5/7, то опять же без скобок получим ошибку. )

    ОтветитьУдалить
    Ответы
    1. > В программировании же четко
      Во всех известных мне языках программирования нет 2-х операций с одинаковым приоритетом, но разной ассоциативность. Поэтому да все однозначно.

      Если приоритеты одинаковые, то как должно выполняться a = b + c? "=" - право-ассоциативно, значит a = (b + c), но "+" - лево-ассоциативно, а значит (a = b) + c? Ассоциативности недостаточно, нужны разные приоритеты! В том же  С++  "+"  приоритетнее "=", поэтому однозначно a = (b + c)

      Если операции с одинаковым приоритетом имеют одинаковую ассоциативность, то что Ваша реализация, что из вики дает одинаковый результат.

      Удалить
    2. > Если приоритеты одинаковые, то как должно выполняться a = b + c?
      Кто раньше встал, того и тапки. ) При одинаковом приоритете первой идет правоассоциативная операция =, поэтому сначала должно быть рассчитано то, что справа от нее, так что a = (b + c) однозначно.
      Есть в вики на эту тему, на русском
      https://ru.wikipedia.org/wiki/%D0%9E%D1%87%D0%B5%D1%80%D1%91%D0%B4%D0%BD%D0%BE%D1%81%D1%82%D1%8C_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B9
      и на английском более подробно
      https://en.wikipedia.org/wiki/Operator_associativity

      Удалить
    3. > Кто раньше встал, того и тапки
      Вот не уверен, что это формально определено, по крайней мере я не смог найти, у арабов раньше вообще справа, а не слева :))) По ссылке на английскую вики: "To prevent cases where operands would be associated with two operators, or no operator at all, operators with the same precedence must have the same associativity."

      Калькулятор кстати зачетный был :))) Я чуток баловался с его предшественником МК-54, помню что батарейки жрал со страшной скоростью и нужно было очень внимательно писать программы, дебажить сложно было :)))

      Удалить
    4. > Калькулятор кстати зачетный был...
      Это да, особенно на фоне полного отсутствия персональной вычислительной техники, так вообще полный восторг.
      Да, они были прожорливы. А с батарейками в те годы была беда. По-моему, щелочных и вовсе не было в СССР, ну или они очень маленькими партиями выпускались, я их не помню. А солевые умирали на раз-два.

      Удалить