Я разделяю отношение автора к происходящим в отрасли процессам. Но не могу согласиться с основным выводом. Никакого разворота, скорее всего, не произойдет. Будет фрагментация. Проекты, где ведутся профессиональные процессы разработки без привлечения шальных денег будут обособляться от модных, но бесполезных проектов, где форма превалирует над содержанием. Этот процесс давно можно наблюдать в науке. Есть люди, ведущие научные исследования, а есть люди, продающие циркониевые браслеты, и они между собой практически нигде не пересекаются.
Полностью согласен. При этом задача IT — создать такую модель, в которой все хотелки заказчика будут работать. А сомнительные результаты будут достаточно подробно документированы.
У меня в одной системе было требование 1.45 = 2. Сделал так, как просили, но чтобы округление так работало, надо было зайти в настройки и явно включить эту фичу, которая по умолчанию была отключена.
Конечно, она в определенных областях незаменима. Но вот тип decimal в матфизике не нужен. Он предназначен именно для точного представления чисел, которые ведутся в десятичной системе счисления. Зачем в C# его плавающим сделали, для меня загадка. И вот этот эффект, когда в сходных случаях наблюдается разное поведение, меня удивляет. В double такого эффекта нет. Там, что 0.1 прибавить, что 100 — если точности не хватило, то число просто увеличено не будет.
Да уж. Я поражен. Оказывается, если к 79228162514264337593543950335m прибавить 0.1, то слагаемое потеряется. А если к этому же числу прибавить 1, то будет OverflowException. Плавающая точка — зло.
Понятно. Вы имели в виду 28 знак справа от точки, а я слева.
На stackoverflow пишут, что формат {:F} в C# всегда округляет до какой-то захардкоженной позиции. Именно поэтому я в примерах умножал на 10^15, чтобы нужные знаки получить. Я просто не нашел формат, в котором нет неявного округления.
Ага, вспомнил, что я хотел сказать. Я хотел возразить вот на это
Аналогично проблемен и Decimal из C#, и даже больше: если каким-то образом вылезли за его 28 цифр, то там даже inexact exception не будет: он не умеет жаловаться на такое.
Что касается покупки-продажи. Речь идет чисто о внутренней реализации. На табло можно надписать что угодно, все равно это никто не читает. А внутри, в коде, вместо терминов покупка-продажа должны быть точные нейтральные термины, которые тяжело спутать.
У меня был реальный случай, когда одна половина команды считала, что операция обозначает покупку иностранной валюты у клиента за рубли, а другая половина команды была уверена, что это покупка валюты у компании. Чтобы разобраться подняли все документы. Везде было слово «покупка», но нигде не уточнялось, кто у кого покупает. Причем, в некоторых согласованных всеми участниками документах были разночтения в проводках. Т. е. даже по проводкам однозначно нельзя было смысл восстановить.
Ну и известный инцидент, когда в одном серьезном банке курсы забили наоборот, в результате можно было купить доллары и тут же их продать дороже, тоже связан с неоднозначностью терминологии.
Конечно, объект ExchangeRate может содержать много дополнительных методов, в том числе и расчет суммы в валюте списания от фиксированной суммы валюты зачисления, но смысл его полей при этом не поменяется. Будет как-то так:
public Sum howManyClientShouldGive(Sum clientWants) {
if (!clientWants.getCurrency().equals(clientTakes.getCurrency())) {
throw new IllegalArgumentException();
}
BigDecimal amount = clinetWants.getAmount().multiply(clientGives.getAmount())
.divide(clinetTakes.getAmount(), PRECISION, BigDecimal.ROUND_HALF_UP);
return new Sum(amount, clientGives.getCurrency());
}
Вообще да, mutable BigDecimal был бы очень полезен. Так как каждое значение в новый объект запихивать может быть очень накладно. Его можно для своих нужд быстренько сделать или готовый скачать.
Я, пожалуй, погорячился насчет экономии, но ради производительности double применять все равно не стоит.
Так ведь нельзя клиенту по этому же курсу продать USD за EUR. Это будет убыток банку. В этом-то то и фишка моей технологии. Нужно создать другой курс с параметрами clientGives: EUR, clientTakes: USD. И там цифры будут другие. Хотя, если вы готовы по тому же курсу в обратную сторону торговать, можно просто переставить значения местами, но это уже будет не бизнес, а благотворительность.
Курс обмена — односторонний, именно поэтому он является вектором.
У меня в одной системе было требование 1.45 = 2. Сделал так, как просили, но чтобы округление так работало, надо было зайти в настройки и явно включить эту фичу, которая по умолчанию была отключена.
На stackoverflow пишут, что формат {:F} в C# всегда округляет до какой-то захардкоженной позиции. Именно поэтому я в примерах умножал на 10^15, чтобы нужные знаки получить. Я просто не нашел формат, в котором нет неявного округления.
Аналогично проблемен и Decimal из C#, и даже больше: если каким-то образом вылезли за его 28 цифр, то там даже inexact exception не будет: он не умеет жаловаться на такое.
Decimal выкидывает Exception.
У меня был реальный случай, когда одна половина команды считала, что операция обозначает покупку иностранной валюты у клиента за рубли, а другая половина команды была уверена, что это покупка валюты у компании. Чтобы разобраться подняли все документы. Везде было слово «покупка», но нигде не уточнялось, кто у кого покупает. Причем, в некоторых согласованных всеми участниками документах были разночтения в проводках. Т. е. даже по проводкам однозначно нельзя было смысл восстановить.
Ну и известный инцидент, когда в одном серьезном банке курсы забили наоборот, в результате можно было купить доллары и тут же их продать дороже, тоже связан с неоднозначностью терминологии.
C#
Исключение при переполнении целой части не выбрасывается, вы правы. Я спутал с decimal.
В C# я проверял — выскакивает ArithmeticOverflowException. А вот Java проглатывает.
Эх, как же скучно я живу.
Я, пожалуй, погорячился насчет экономии, но ради производительности double применять все равно не стоит.
Курс обмена — односторонний, именно поэтому он является вектором.
Когда все суммы положительные, то не нужен ни плюс, ни минус. Поэтому я считаю, что моя модель проще. Мне не нужно ничего запоминать.
У вас дебет — это плюс? Т. е. вы от кассы считаете? Вам так удобно?
Если бы я использовал плюс-минус, то у меня дебет был бы минус.