Найти в Дзене
Программы от меня

Как я писал калькулятор на C# и MAUI, или Почему 2+2 иногда равно 5

Вступление: "Зачем велосипед, если есть Excel?" Привет, мои любознательные читатели! Если вы думаете, что программисты только и делают, что взламывают Пентагон и пишут нейросети для определения сортности бананов, то вы ошибаетесь. Иногда мы занимаемся гораздо более важными вещами. Например, созданием калькулятора. Да-да, того самого приложения, которое уже 30 лет встроено в каждый утюг, Windows и даже в часы за 100 рублей на рынке. Но мне, как человеку, который любит ходить по граблям, захотелось написать свой. И не абы как, а с использованием C# и фреймворка .NET MAUI (Мультиплатформенный рукож*... простите, универсальный интерфейс приложений). Зачем? Чтобы он считал не только на компе, но и на телефоне. А вдруг я окажусь на необитаемом острове, где будет только iPhone с Windows 11, а встроенный калькулятор сломается? Надо быть готовым ко всему. Для тех, кто не в танке: MAUI — это штука, позволяющая писать код на C# и раскидывать его на Android, iOS, macOS и Windows. Один код — чет
Оглавление

Вступление: "Зачем велосипед, если есть Excel?"

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

Да-да, того самого приложения, которое уже 30 лет встроено в каждый утюг, Windows и даже в часы за 100 рублей на рынке. Но мне, как человеку, который любит ходить по граблям, захотелось написать свой. И не абы как, а с использованием C# и фреймворка .NET MAUI (Мультиплатформенный рукож*... простите, универсальный интерфейс приложений).

Зачем? Чтобы он считал не только на компе, но и на телефоне. А вдруг я окажусь на необитаемом острове, где будет только iPhone с Windows 11, а встроенный калькулятор сломается? Надо быть готовым ко всему.

Что за зверь MAUI?

Для тех, кто не в танке: MAUI — это штука, позволяющая писать код на C# и раскидывать его на Android, iOS, macOS и Windows. Один код — четыре платформы. Мечта ленивого разработчика. Звучит круто, да? На деле же это похоже на попытку накормить одной котлетой льва, орла и золотую рыбку. Но мы не ищем легких путей.

Этап 1: Интерфейс, который я хотел вырвать с корнем

Первым делом открываем Visual Studio. Если у вас она не установлена, то поздравляю — вы сэкономили 3 часа жизни и 20 гигабайт места на диске. У меня же установлена, так что пути назад нет.

Создаем проект MAUI Calculator.
Студия радостно генерирует кучу файлов. Я смотрю на папку Platforms и впадаю в ступор. Там есть папки для Android, iOS, Windows... Чувствую себя капитаном космического корабля, который случайно нажал красную кнопку.

Нам нужен файлик MainPage.xaml. Это разметка, как в HTML, только злее.

Я леплю Grid с кнопками. Это как в детстве собирать конструктор, только если деталь встала не на место, оно не падает, а просто не компилируется.

Вот кусочек моего гениального дизайна (для кнопки «7»):

<Button Text="7"
Grid.Column="0" Grid.Row="1"
Clicked="OnNumberClicked"/>

Я тут же почувствовал себя Стивом Джобсом. Минимализм, чистые линии, а главное — понятно, что это кнопка 7. Гениально!

-2

Этап 2: Логика. Самое сложное — сделать вид, что это сложно

Переходим в MainPage.xaml.cs.
Нам нужно хранить текущее число, предыдущее число и выбранную операцию. Объявляем переменные:

  • _currentNumber — что сейчас на экране.
  • _previousNumber — что мы ввели до нажатия на плюс/минус.
  • _operation — +, -, * или /.

Сначала пишем обработчик для цифр. Казалось бы, что проще? Нажал на кнопку — добавил цифру в строку. Но C# — строгий парень. Он не любит, когда строку пытаются превратить в число, а там пусто.

Поэтому я пишу:

private void OnNumberClicked(object sender, EventArgs e)
{
var button = (Button)sender;
_currentNumber += button.Text;
ResultLabel.Text = _currentNumber;
}

Работает! Я гений. Нажимаю «1», потом «2» — на экране «12». Красота.

Этап 3: Проблема с плавающей точкой, или Сюрприз от создателей IEEE 754

Добавляю кнопку с запятой.
Тут начинается веселье. Нужно проверять, чтобы запятая была только одна. Пишу условие: if (!_currentNumber.Contains(",")). Добавляем запятую. Работает.

Но потом я решаю поделить 10 на 3.
Нажимаю: 10 / 3 = .
И тут на экране появляется
3,3333333333333335.
Почему пять в конце?! Откуда она взялась?! Кто подбросил эту лишнюю пятерку?!
Друзья, знакомьтесь — это погрешность вычислений с плавающей точкой. Компьютер считает в двоичной системе, а мы в десятичной. Для него 1/3 — это примерно как для нас разделить 10 рублей на троих друзей, но при этом один друг требует отдать ему копейку, потому что "так в матрице написано".

Я мог бы полезть в дебри, использовать decimal вместо double, но решил оставить эту пятерку как пасхалку. Пусть пользователи думают, что это новая фича от Microsoft — "Калькулятор с сюрпризом". Кто найдет лишнюю 5, тот получит приз (приз — утешение, что вы не сошли с ума).

Этап 4: Тестирование на живых людях

Запускаю приложение на Windows. Работает.

Работающий калькулятор MAUI
Работающий калькулятор MAUI


Пытаюсь запустить на эмуляторе Android. Эмулятор грузится 40 минут. За это время я успеваю сходить за чаем, приготовить бутерброд и забыть, что я вообще делаю.
Наконец, он запускается.
Кнопки мелкие, тыкаю пальцем — промахиваюсь. Экран телефона явно не рассчитан на мои "слоновьи" пальцы программиста.
Нажимаю "5", а попадаю в "8". Калькулятор живет своей жизнью. Я ввожу "2+2", а он выдает "5". Вот оно! Я создал идеальный калькулятор для бухгалтеров-оптимистов!

Заключение: "А можно просто виндовый?"

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

Стоило ли оно того? Конечно, да!
Теперь я могу носить в кармане (на телефоне) приложение, которое я написал сам. И когда друзья просят посчитать процент по вкладу, я достаю телефон и говорю: "Ща, погоди, запущу свой софт".
Друзья обычно округляют глаза и спрашивают: "Ого, ты что, программист?". Я важно киваю и показываю им баг с делением 10 на 3. Друзья перестают спрашивать у меня советы по финансам.

Мораль: Если хотите научиться программировать под мобилки — пишите калькулятор. Это просто, весело и наглядно показывает, что даже в самом простом коде может прятаться маленький зеленый гоблин с табличкой double.

Если хотите просто скачать готовые коды моей проги, не парясь - качайте коды программы из этой статьи с
gitfilc (здесь).

А я пошел фиксить баг с запятой, чтобы нельзя было ввести "2,2,2". Хотя, может, это новый тренд — троичные калькуляторы?

Подписывайтесь, чтобы не пропустить статью по MAUI или еще по какой-нибудь фиче C#!