Чому кастомний калькулятор у мобільному застосунку бреше
Кастомний калькулятор у мобільному застосунку майже ніколи не бреше навмисно — він помиляється на дрібницях, які накопичуються. Користувач додає три позиції, перераховує вручну і не збігається.
Розбіжність може бути лише в останньому знаку, але далі неважливо, хто правий: довіру до розрахунку втрачено, а підтримка отримує суперечку, яку нічим закрити.
Під капотом зазвичай двійкова арифметика з плаваючою точкою, де 0,1 і 0,2 у сумі дають не рівно 0,3. На одній операції це непомітно, а на довгому кошторисі з десятків рядків похибка округлення накопичується і спливає в підсумку — причому по-різному залежно від порядку доданків.
Друга причина — різні формули на різних екранах. Калькулятор у картці, перерахунок у кошику та вивантаження документа живуть на власних реалізаціях: десь знижка рахується до податку, десь після, десь округлення йде вгору. Те саме замовлення дає три різні підсумки, і користувач ловить застосунок на цьому першим.
Третій шар — ручне введення та розбір формул. Крапка чи кома як роздільник, пробіли між розрядами, від’ємні значення, вставлення числа з буфера, користувацький вираз з дужками: кожен необроблений випадок дає мовчки неправильний результат замість помилки введення.
Розбираємо, як це закривається єдиним розрахунковим шаром: десяткова арифметика замість плаваючої, одне місце для правил округлення, спільні формули для всіх екранів і покриті перевірками сценарії розбору — щоб підсумок збігався і на екрані, і у вивантаженні.
Що дає обчислювальне ядро, зібране під задачу
Арифметика в розрахунковому застосунку ламається не на додаванні, а на краях: округленні податків, перерахунку при зміні одиниць вимірювання, довгих ланцюжках операцій із проміжними збереженнями.
Якщо формули продубльовані в інтерфейсі та у фоні, гілки починають розходитися в молодшому розряді — і це найдорожча категорія дефектів, бо відтворюється не в кожного користувача.
Обчислювальне ядро вирішує це архітектурно: єдине джерело формул, яке викликають усі екрани та фонові задачі.
Ми збираємо його як окремий модуль на Kotlin Multiplatform і підключаємо до обох платформ — правка коефіцієнта чи порядку операцій робиться в одному місці й не потребує двох незалежних релізів.
Усередині — десяткова арифметика з фіксованою точністю, явні правила округлення на кожному кроці та розбір виразу в дерево: порядок операцій задано структурою, а не порядком викликів у коді екрана.
Швидкість перерахунку на довгих сценаріях тримається на інкрементальному обході дерева та кеші проміжних вузлів.
Коли користувач змінює одне поле в ланцюжку з десятків пов’язаних значень, перераховується лише залежна гілка, решта береться з кешу — таблиця оновлюється без помітної затримки, а профілювання йде на реальних сценаріях, а не на синтетиці.
Далі ефект рахується в підтримці. Єдине джерело формул прибирає розбіжності між платформами, тому частка спірних розрахунків падає, а звернення зміщуються з «у мене не збігається» на питання про використання.
Навантаження на підтримку перестає залежати від кількості релізів: контрольні набори значень в автотестах фіксують результат, і будь-яке відхилення ловиться до випуску.
Способи реалізації розрахункової логіки в продукті
Розрахункова логіка може жити на пристрої, на сервері або в гібридній схемі — цей вибір визначає поведінку продукту при обриві мережі, швидкість правки формул і те, де осідає історія операцій. Нижче — реальні варіанти, між якими обирають, разом із їхніми слабкими місцями.
| Варіант | Коли підходить | Обмеження |
|---|---|---|
| Розрахунок на пристрої | Формули стабільні, потрібен миттєвий відгук і повна робота без мережі | Правку формули не можна випустити без нової версії застосунку; поведінку на різних платформах доводиться звіряти окремо |
| Розрахунок на сервері | Правила змінюються часто, потрібен єдиний результат для всіх користувачів | Без мережі калькулятор не рахує; кожен крок залежить від каналу зв’язку; історія операцій залишає пристрій |
| Гібридна схема | Потрібні обидві властивості: швидкий відгук і керовані ззовні правила | Складніше складання, потрібна явна механіка синхронізації результатів і розв’язання конфліктів версій формул |
Як обираємо варіант
Розвилка впирається в два питання: як часто змінюються правила розрахунку і чи зобов’язаний продукт рахувати без мережі. Якщо формули стабільні, а зв’язок у користувача не гарантований — рахуємо на пристрої та оновлюємо правила разом із релізом.
Якщо правила правляться постійно й важлива однакова відповідь для всіх — виносимо розрахунок на сервер. Гібрид беремо, коли потрібні обидві властивості: локальний рахунок для відгуку й роботи без мережі плюс спільні правила та синхронізація результатів, коли зв’язок з’являється.
Етапи розробки розрахункового модуля
Розрахункове ядро ламається не на інтерфейсі, а на арифметиці: неправильне округлення на проміжному кроці дає розбіжність з еталоном, яку помічають уже користувачі. Тому порядок робіт будуємо так, щоб код писався після узгодженої схеми, а не паралельно з нею.
-
Розбір формул. Збираємо першоджерела: нормативні документи, таблиці, файли, за якими рахують вручну. Для кожної формули фіксуємо входи й виходи, одиниці вимірювання, правила округлення, поведінку при діленні на нуль і виході за діапазон.
-
Схема розрахунку. Будуємо граф залежностей: які величини первинні, які обчислюються, де допускається проміжне округлення. Схему узгоджуємо письмово — правка на цьому етапі коштує хвилини, у готовому застосунку — переписування ядра.
-
Реалізація. Парсинг введення (локаль, роздільники, експоненційний запис) відокремлюємо від обчислювального ядра — воно залишається чистою функцією без стану. Точні величини рахуємо в десятковій арифметиці замість чисел із плаваючою точкою.
-
Тестові набори. Еталонні приклади від замовника доповнюємо граничними випадками: максимуми, від’ємні значення, нуль, повторне застосування операції, зміна одиниць.
-
Перевірка результатів. Проганяємо набори автотестами з допуском за останнім знаком, розбіжності розбираємо до нуля. Рахуємо на реальному обсязі даних, а не на трьох показових прикладах.
-
Передача модуля. Віддаємо документацію щодо формул, схему розрахунку, тестові набори в репозиторії та опис правил округлення. Навчаємо команду й залишаємося на підтримці — модуль розвивається без нас.
Що команда замовника отримує за підсумками роботи
Готовий застосунок без документації живе до першої зміни формули: розрахунок розходиться з очікуванням бізнесу, а знайти місце правки нікому.
Тому за підсумками роботи передаємо не збірку, а повний робочий комплект — за кожним артефактом видно, як рахується результат і хто має право його змінювати.
- Вихідний код — репозиторій з історією змін і розділеними шарами: розбір введення, обчислювальне ядро, відображення. Складається з чистої гілки однією командою, без ручних правок на машині розробника.
- Опис формул — таблиця відповідності «бізнес-правило → формула → джерело вимоги». Суперечка про те, яка ставка чи коефіцієнт правильні, вирішується звіркою з цим документом, а не листуванням.
- Схема даних — що рахується й зберігається на пристрої, що йде на сервер, як версіонуються збережені розрахунки. Старі записи читаються після зміни формату.
- Права доступу — ролі співробітників замовника: хто змінює коефіцієнти, хто затверджує випуск версії, де лежать ключі підпису й як вони відкликаються при звільненні людини.
- Регламент оновлення — як випустити нову формулу, не випускаючи нової версії застосунку: набір правил перевіряється на еталонних розрахунках, відкат — повернення попереднього набору.
- Еталонні розрахунки — добірка граничних випадків: нулі, від’ємні значення, округлення, роздільники дробової частини, порядок операцій. Розбіжність ловиться до виходу, а не за скаргою клієнта.
- Інструкція щодо середовища та складання — які інструменти потрібні, як підняти складальний контур з нуля і як випустити застосунок у магазини з акаунта замовника.
Практика: перерахунок кошторисів у будівельному сервісі
Що було
Кошториси за об’єктами рахували у два проходи: інженер заміряв обсяги на майданчику й фіксував їх у блокноті, а в офісі переносив ті самі позиції в 1С і перераховував вручну. Другий прохід займав 40–60 хвилин на об’єкт і фактично був єдиною перевіркою першого. Розбіжності спливали вже на етапі акта — коли обсяги закупівлі та наряди бригадам були підписані.
Причини були системні: різні правила округлення на майданчику й в офісі, різні формули для коефіцієнтів, загублені під час перенесення позиції.
За нашими замірами 6–9% підсумків за об’єктом не збігалися, а звернення до підтримки щодо арифметики в кошторисі давали близько третини всіх заявок першої лінії.
Що змінили
Формули винесли в один модуль: кастомний калькулятор у мобільному застосунку, офісне робоче місце та вивантаження в облікову систему рахують за одними правилами й з однією точністю.
Чернетка рахується на майданчику без зв’язку, при появі мережі йде на сервер, а автозвірка порівнює підсумки порядково й підсвічує розбіжність до відправлення — спірні позиції розбирають на об’єкті, а не в листуванні із замовником.
Після впровадження розрахунок за об’єктом займає 8–10 хвилин замість 40–60, ручний перерахунок як окремий етап прибрано.
На контрольній вибірці об’єктів розбіжностей у підсумках між чернеткою та фінальним кошторисом — нуль, частка звернень до підтримки щодо розрахунків упала нижче 2%.
Чим відрізняється розрахунок на пристрої від розрахунку на сервері
Якщо формула рахується прямо на пристрої, результат з’являється в момент дотику: немає запиту, немає очікування відповіді, немає залежності від якості каналу.
У ліфті, на складі, у роумінгу застосунок продовжує рахувати, а введені проміжні значення залишаються в локальному сховищі.
Розрахунок на сервері дає одне джерело формул: довідники та коефіцієнти змінюються без випуску нової версії, історія розрахунків доступна з будь-якого пристрою.
Плата за це — затримка на кожному кроці та повна непрацездатність без мережі: калькулятор перетворюється на форму, яка чекає на відповідь.
Окрема тема — однаковість. Дійсні числа розходяться в молодшому розряді за різного порядку операцій, тому суми ведемо в цілочисельних мінорних одиницях, а правило округлення фіксуємо явно й описуємо як у IEEE 754.
Еталонні набори входів проганяємо через обидві реалізації та звіряємо результат до останнього знака.
Найдорожче коштує підтримка двох копій логіки: два джерела істини неминуче розходяться, і тоді перерахунок підсумків заднім числом видає інші суми в уже закритих документах.
Лікується спільним модулем розрахунку, який збирається з однієї кодової бази під обидві платформи, версією формули всередині кожного збереженого розрахунку та міграцією при її зміні.
На практиці робоча схема гібридна: рахунок іде на пристрої, а сервер відповідає за довідники, синхронізацію та перерахунок історії за запитом. Тоді відзивчивість і робота без мережі залишаються в користувача, а однаковість формул — під контролем на стороні сервісу.
Технічні сумніви перед стартом роботи
Перед стартом інженерна команда ставить ті самі питання: як забезпечується точність, що відбувається при зміні формул, чи можна вбудувати розрахунок у вже працюючий застосунок і як довести, що попередні підсумки не поїхали. Нижче — відповіді по суті.
Наскільки точним буде розрахунок?
Рахуємо в десятковій арифметиці з фіксованою шкалою, а не в двійковій із плаваючою точкою: довгі ланцюжки нарахувань не накопичують похибку, а підсумок збігається до останнього знака.
Правило округлення задається явно — до найменшої частки, половина вгору або за банківською схемою — і закріплюється перевірками на граничних сумах, де розбіжність проявляється найраніше.
Що буде, коли формули зміняться?
Формули, тарифні сітки та коефіцієнти описуємо декларативно й виносимо в конфігурацію, а не в код. Нове правило або змінений тариф підхоплюються під час чергового запуску — перескладання та повторна публікація в магазинах не потрібні.
У нас уже є своя логіка розрахунку — як бути?
Зберігаємо її поведінку як еталон: до першого рядка нового коду звіряємо підсумки на ваших прикладах, а саме ядро розрахунку виносимо окремим модулем за стабільним інтерфейсом. Обв’язку та перехід робимо частинами, не зупиняючи поточний застосунок.
Як перевірити незмінність попередніх результатів?
На старті фіксуємо набір еталонних сценаріїв: тарифні зрізи, граничні суми, знижки, валюти. Кожне складання проганяє його та порівнює зі збереженим підсумком — розбіжність хоча б в одному знаку блокує випуск.
Набір передаємо вам разом із документацією, тому перевірку можна повторювати власними силами й після передачі.
Обговоримо задачу й повернемося з оцінкою та планом
Щоб повернутися з оцінкою та планом робіт, а не з уточнювальними питаннями, нам достатньо одного листа з описом задачі. Чим конкретніші вихідні дані щодо кастомного калькулятора, тим менше припущень в оцінці й тим реальніші строки.
- Що рахує калькулятор: перелік формул, порядок операцій, правила округлення та вимоги до точності на довгих ланцюжках обчислень.
- Як користувач вводить дані: покроковий майстер, вільний вираз із розбором синтаксису або імпорт значень із таблиці.
- Платформи та мінімально підтримувані версії системи, чи потрібна робота без мережі та перенесення результату між пристроями.
- Що вже є: макети, прототип, таблиця з формулами або попередня версія застосунку, з якою потрібна сумісність.
- Інтеграції та довідкові дані: курси, тарифи, зовнішні сервіси, вивантаження результату у файл або надсилання на пошту.
- Доступи: акаунти магазинів застосунків, репозиторій, стенди й тестові дані — їх можна передати на етапі старту.
- Обмеження: строки, у які потрібно вкластися, і платформа, яка в пріоритеті.
На основі цього ми повернемося з планом робіт за етапами, оцінкою строків і складом команди: хто відповідає за розрахункове ядро, хто за інтерфейс і складання.
Якщо якихось даних не вистачає, позначимо це окремо й запропонуємо, як закрити до старту — опишіть задачу, і ми повернемося з оцінкою та планом.







