
Комментарии 25
Какой кошмар.
За вещественные числа в финансовых приложениях в реальной жизни могут побить палкой. Это не вопрос компромисса.
В чем кошмар то)? Скажем для ипотеки на 20 лет погрешность будет меньше одной сотой копейки
Как принято говорить в таких случаях, если нужно объяснять, то не нужно объяснять.
Ну я согласен с посылом если бы это было бы действительно банковским приложением но в моем случае это не так
А что это в вашем случае? Рисователь каких-то цифирек? А потом пользователь будет удивляться почему ваш калькулятор показывает одно, а банк "немножко другое"?
Если бы беретесь за какие-то финансовые расчеты - делайте это по правилам, принятым для финансовых расчетов. Или не делайте вообще.
А я не согласен, потому что ваш оппонент не сможет объяснить, как не смогли все с кем я разговаривал последние 10 лет. Причем финансовыми вычислениями на основе float математики занимаются почти все, например я видел вагон реализаций корзины интернет магазина, и ни одна из них не делала вычисления базой (а это единственный способ имея php+js использовать честный numeric). Максимум - php bcmath, у которого во первых своих глюков немеряно, во вторых котором унужно базу вычислений задирать в небеса (что сделано не было). А чаще умножение/деление на 10 на каждый чих что во первых не является безопасной операцией с точки зрения точности, а во вторых делает хуже. И уж совсем редко храненеи в базе в качестве целых чисел, что просто не работает в общем случае, по целому ряду причин.
А самое веселое что все это и не нужно, с float все ок, бывают нюансы, да, но я сейчас посидел и не вспомнил ни одного неустранимого при точности ~(3+4+3+2) знака после запятой, кроме человеческого фактора и различий в подходе к ведению документов.
Причем финансовыми вычислениями на основе float математики занимаются почти все, например я видел вагон реализаций корзины интернет магазина, и ни одна из них не делала вычисления базой (а это единственный способ имея php+js использовать честный numeric)
Финансовые вычисления это прежде всего банки, страховые, налоговые.
И реализуются они точно не на "php+js".
Это прежде всего интернет магазины, маркетплейсы, всевозможные учетные системы.
Но раз уж вы заговорили про банки, поверьте, вам лучше не знать на чем они и как и какие веселости там происходят.
Но опять же, по существу будет чтото?
Но раз уж вы заговорили про банки, поверьте, вам лучше не знать на чем они и как и какие веселости там происходят.
Ну я как-бы немного в курсе как оно там работает. Причем, на уровне центральных серверов. Ядра АБС.
Это прежде всего интернет магазины, маркетплейсы, всевозможные учетные системы.
И что там? Каждый день пересчитываются проценты (кредиты/депозиты)? Есть мультивалютные проводки (в курсе как они организованы) ?
В курсе что в банке баланс сводится каждый день (закрытие банковского дня)? И он должен сойтись.
Все это сильно сложнее чем просто просуммировать товары в корзине.
Кривая реализация на костылях не означает нормальность. Нормально - использовать наиболее подходящий для решения задачи инструмент.
Сударь, вы по технической части что-то имеете сказать? Мерятся и холиварить с вами я не буду (но если хотите, то у меня больше и толще).
Чтото не подходит? Объясните почему.
По технической части все уже сказано неоднократно.
Ошибки округления (см. рекуррентное соотношение Мюллера) при множественных операциях с плавающей точкой (вычисление процентов, в т.ч. "сложных процентов" и процентов на проценты, конвертация валют и т.п.).
Ошибки переполнения.
Производительность при высоких нагрузках и больших объемах данных (сотни миллионов банковских операций в сутки, сотни миллионов операций, в т.ч. связанных с начислением процентов, при закрытии банковского дня)
Ссылок тут уже было предостатчоно.
По технической части все уже сказано неоднократно.
Не аргумент
Ошибки округлени
Вынуждают понимать математику финансов и знать налоговый кодекс даже если вы используете нумерик.
Ошибки переполнения.
На масштабах которые 99,99 разработчиков не видели не знают и не узнают, а надувают щеки вообще все
Производительность при высоких нагрузках и больших объемах данны
У вас есть данные подтверждающие это утверждение?
Ссылок тут уже было предостатчоно.
Будьте добры парочку
И как это все относится к случаю автора кстати?
Ниже оставлю текст который я с Джемини составил для молодых инженеров которые сюда забредут. Фраза «если нужно объяснять, то не нужно объяснять» — это интеллектуальная капитуляция. В инженерном деле, если ты не можешь объяснить поведение системы на цифрах и примерах, значит, ты просто веришь в магию. Приправленной бессмысленным хамством, основанным на вырванных из контекста академических знаниях, это все заставляет меня грустить, поскольку я все еще в глубине души верю, что инженеры несколько выше этого.
1. Рекуррентное соотношение Мюллера
Это звучит умно, но это специфический пример, где итеративная формула при использовании float уходит в бесконечность.
Упоминание Мюллера в контексте финансов — это чистая демагогия. Его последовательность специально сконструирована так, чтобы ошибка взрывалась на миллионах итераций в неустойчивых формулах.
Почему в кредитах это мимо: Даже в ипотеке на 30 лет всего 360 итераций (месяцев). Погрешность
doubleначинает «плыть» на таких операциях спустя миллионы шагов. Более того, банковский регламент требует округления до копейки на каждом шаге начисления, что физически «сбрасывает» микро-ошибку флоата в ноль каждый месяц.Почему в торгах это мимо: У нас нет рекуррентных зависимостей. Расчет каждой транзакции — это линейная операция. Ошибка здесь не копится, она предсказуема и полностью нивелируется методом «тянуть точность до финального документа».
2. Ошибки переполнения
Аргумент из прошлого века. Double (64 бита) держит значения до \(1.8 \times 10^{308}\). Скорее «безопасное целое» (Integer) переполнится при попытке перемножить курс с объемом, чем вы вылетите за пределы мантиссы флоата в расчете транзакции.
3. Производительность
Нативная арифметика float/double — это самое быстрое, что умеет процессор (FPU). Любые Decimal/Numeric/etc — это программные надстройки, которые в десятки раз медленнее. На High-load торгах в реальном времени у вас просто нет времени на «строковую математику».
4. Миф о «чистоте» Integers
Если данные прилетают из API биржи как float (например, 1.2345), они уже имеют погрешность представления. Попытка умножить их на \(10^{n}\) и запихнуть в целое число не «исцелит» данные, а просто зафиксирует ошибку. Использовать BigInt ради этого — бессмысленная трата ресурсов.
5. Округлять промежуточно — НЕЛЬЗЯ
Большинство ошибок «флоата» — это ошибки вашего алгоритма. Нельзя округлять промежуточные суммы, налоги или конвертации. Округление — это не математическая операция, а финализация данных для вывода (UI или печать). Мы тянем точность через всю цепочку до самого инвойса.
6. Детерминизм через самописные функции
Проблема не во флоате, а в разнице реализаций round() в разных средах. Единственный путь к 100% сходимости фронта и бэка — свои функции округления (например, Round Half Up), работающие по единому алгоритму.
7. Кросс-платформенная валидация
Вместо того чтобы бояться гипотетических ошибок, инженер внедряет кросс-валидацию между фронтом, бэком и БД. Если расчеты сходятся в 99.9% случаев, а оставшийся 0.1% — это не «магия процессора», а разница в логике, которая правится кодом, то система становится надежнее любого "черного ящика" типа банковского ПО, где ошибки просто зарывают в «курсовые разницы» или комиссии.
8. Масштабируемость точности (The "Buffer Zone")
Когда расчет ведется на 10 знаках, а финансовый документ требует всего 2 (или 3 для цены), накопленная «мусорная» часть флоата остается глубоко за пределами значимых разрядов. Она просто не способна «доплыть» до копеек при финальном округлении, если ты не делаешь промежуточных итераций. Это делает систему устойчивой к любым артефактам IEEE 754 /
PS и напоследок текст от gemini без редактуры
Разговоры о том, что флоат — это «кошмар» — это признак того, что человек никогда не строил системы, где производительность и точность должны работать одновременно. Они выбирают «безопасные» инструменты, потому что боятся ответственности за понимание того, как числа лежат в памяти.
PSPS статью запилить чтоле...
А попробуйте, например мне, занимающемуся мультивалютными расчетами высокой точности в реальном времени на яваскрипте
PS оперативно вы, но если по существу сказать нечего то на этом и закончим
На фоне того, что вы не считаете количество дней в месяце (а большинство банков считает именно по дням), а просто делите ставку на 12, такая точность нафиг не нужна.
Вот на самом деле вы правы, не один расчет не будет точен если у него нет календаря конкретного банка с учётом их выходных и праздников, по поводу погрешности она может достигнуть нескольких тысяч рублей но на длинной дистанции кололо года она частично самокомпенсируется. Для трекеров стратегий это абсолютно приемлимо ТК цель дать ответ гасить ли долг
По поводу математики - все суммы в банковских БД обычно хранятся в миноритарных единицах. Формат полей - типы с фиксированной точкой (обычно - decimal, есть еще numeric, но там внутренне представление другое, decimal компактнее).
В подавляющем большинстве случаев хватает decimal(15, 0), в исключительных - decimal(23, 0).
В языках, разработанных специально для коммерческих вычислений (COBOL, RPG...) эти типы нативно поддерживаются самим языком (безо всяких костылей типа BigDecimal). В RPG decimal -> packed, numeric -> zoned. Естественно, что там же поддерживается и вся арифметика, включая операции с бухгалтерским округлением (в RPG просто пишем eval(h) a = b / c вместо a = b / c)
Работа с float/double, а еще итеративная, может преподнести забавные сюрпризы (см. рекуррентное соотношение Мюллера).
Вообще, про коммерческие вычисления было уже
Заложники COBOL и математика. Часть 1
Заложники COBOL и математика. Часть 2
Также следует обратить внимание на возможность переполнений. В системах, ориентированных именно на коммерческие вычисления переполнение вызывает системное исключение (как деление на ноль). Вам же придется за этим следить руками. Обычно объявляется временная переменная с максимально поддерживаемой размерностью, результат заносится туда, потом проверяется, не превышает ли он размерности целевой переменной и только в случае положительного ответа уже переносится в целевую.
Это если все делать правильно.
С одной стороны я согласен, с другой стороны, можно ли на практике получить хоть сколь-нибудь существенные отклонения считая в даблах?
Тут шагов то 50*12 = 600 максимум и никаких экстремальных сум.
Отклонение в сумме платежа в одну копейку достаточно для получения большого штрафа или другого наказания. Тем более если речь идёт о погашении кредита.
Согласен, для банковского бэкенда и учета реальных денег Double это табу. Там только Long в копейках или Decimal.
Но тут выбрал другой компромисс. На дистанции в 240 месяцев погрешность Double меньше сотой доли копейки. Для стратегии какой кредит гасить первым этой точности за глаза, зато код в Room и во ViewModel остается лаконичным и быстрым.
За ссылки на COBOL спасибо)
Тогда надо сразу предупреждать крупными буквами что вычисления приблизительные, не соответствуют банковским правилам. Только оценка.
За ссылки на COBOL спасибо)
Да не за что :-)
Если интересно, есть еще. Уже мое (почти 9 лет в этом кручусь, правда, моя тема комплаенс, клиентские данные всякие террористы-экстремисты, санкции, риски и т.п., счета-платежи практически не бывает в работе, этим другие команды занимаются).
Современный RPG — что может и зачем нужен
Способы работы с БД DB2 в языке RPG на платформе IBM i
Экзотика, но ы РФ на этом работали (на уровне центральных серверов и ядра АБС) Райф, Росбанк, Альфа (и Альфа-Страхование), Ак-Барс. Мы (Альфа) пока еще на ней продолжаем, про остальных не в курсе.
Какое-то время назад таки машины были еще в ПФР и РЖД. Сейчас не в курсе что там, скорее всего нет уже.
А как сервис то называется ?
Как мы считаем досрочное погашение кредита: что реально работает в коде