Случился спонтанный ликбез по поводу float-ов в биллинге:
http://amarao-san.livejournal.com/2944300.html То, что программисты через одного не понимают, что такое плавающая точка и какой физический смысл расчетов в ней, это вымораживает конечно каждый раз.
Расчет посуточный. А списание как надо.
Алгоритм простой. Цена задается за период. Период состоит из месяцев и дней. Годы не нужны, т.к. год всегда 12 месяцев.
Из расчета периода рассчитывается цена дня в -текущем- периоде, т.е. берется цена периода и делится на число дней в нем. Она дробная с высокой точностью. Но если период закрывается целиком, ты её нигде не видишь.
Считается день окончания периода. Чтобы 28, 30 и 31 считались правильно, даю хинт: правильный ход "на месяц вперед" записывается как date.addDays(1).addMonths(1).addDays(-1). Можешь проверить, любая високосность отрабатывается так, что получается месяц вперед в людском понимании.
Дальше если период придется прервать (= сделать расчет до дня), то дробная с высокой точностью цена умножается на кол-во нужных дней. Если там получилось 3.(3) и пришлось её умножить на 6, получится 20. Как пример.
Если на 1, то получится 3,33, это придется, конечно, округлить. Неразмеченная часть будет при этом 97.67, что правильно.
Либо 6.67 и .33 наоборот.
Всё работает
1) с правильной точностью
2) генерит правильные списания в случае частичных списаний с точностью до дня
3) никто никогда не видит этих периодов, потому что они только внутри как промежуточный инструмент
4) месяц - это месяц, а не неведомая фигня, как у тебя с Шорсом в примерах
Reply
Именно по этому у нас для юриков оплата помесячная (все равно они по договору раз в месяц платят) а для физиков - посуточная (и нету больше проблемы ему объяснять что за 31 января ему надо заплатить столько, а за 1 февраля - вот столько).
А уж если юрик разорвёт договор в середине месяца - бухгалтерия уж как нибудь ему на калькуляторе посчитает сколько надо оплатить а сколько вернуть.
Reply
Он в этом смысле полностью универсален. Но при этом можно также честно писать месячную цену, и годовую цену.
Это не другой алгоритм. Это просто нормальный полноценный алгоритм, который любым раком потом можно поставить и он будет считать правильно. Правильный подневный расчет при необходимости - его подмножество.
Reply
Если первое - не надо, я тебе на слово верю (тем более проверять - уже голова не варит, а ты утверждаешь что ты им пользуешься, т.е. он как минимум "проверен временем").
Если второе - тоже не надо. Вот тебе выдержка из нашей переписки с schors-ом в жуйке:
Reply by @ufmufm
dmh на самом деле прав в том, что правильно работать с флоатом умеют еденицы. И такой лютый пиздец из-за этого иногда на выходе происходит, что пресловутая "1 копейка не сошлась" - это за счастье будет. Поэтому мне проще было сказать "дробных копеек не бывает" и после этого знать, что если в накатанном на коленке младшим админом скрипте он сравнит две суммы на равенство - они адекватно будут сравнены.
Reply by @schors:
а с целочисленными все сразу начинают правильно работать? или там хвосты от делений на подарки уходят? или ты запрещаешь делить? :)
Reply by @ufmufm
запрещаю делить (точнее - в обычной жизни делить не приходится, а если хочется странного - то это повод задуматься в данном конкретном месте как поступить правильно). Зато 0.01+0.01+0.01+0.01+0.01+0.01+0.01+0.01+0.01+0.01 всегда строго равно 0.01*10
Reply
Reply
Reply
Reply
В декабре и январе 31 день. 124/31 - 4 рубля в день.
В феврале - 28. - 4.42 в день (4.428571429, если в любимом тобой флоате, но это не важно).
Абонент заплатил 4 января 124 рубля, из расчёта, что ему хватит до 4 февраля (он же платил 4-го декабря, и ему хватило!!!!!1111адинадин)
А на самом деле.
124-28*4= 12
Т.е. ему в феврале 12 рублей не хватит на 3 дня хоть с флоатом хоть без.
Reply
Reply
Reply
P.S. Я торгую интеренетом, если чо. Т.е. не хостингом. :)
Reply
Reply
Reply
Мало того, абонент может менять тариф среди месяца.
Т.е. у меня нет возможности расчитывать стоимость периода. Только стоимость 1 дня. А тут как не крути - (стоимость тарифа в месяц)/(дней в месяце).
Reply
Либо ты указываешь на сайте цену дня, либо указываешь на сайте цену месяца.
Если цену дня, то разговор можно закрыть. Всё просто предельно. Или цену 30 дней, что оно и то же.
Либо ты указываешь цену месяца.
Либо - что ты 5-й раза уже пишешь в примерах - ты указываешь цену 30 дней а ТВОЙ (не мой!) клиент думает, что это цена месяца. Вот эти вот твои примеры постоянные про 4-е число и раньше хватало !!!адынадын - это от того, что ты выставил цену ДНЯ, а клиент её понял как МЕСЯЦА.
Потому что месяца, вообще-то, логичнее.
И в рекламе у вас поди не дни указаны, а месяцы всё-таки.
И вот твой клинический пример про 4-е числа и желание клиента "раньше же хватало" - мой биллинг - решает. Если раньше хватало, то хватит и сейчас.
Твой - нет.
Вот собственно и всё.
При этом, желание клиента класть туда произвольные суммы перпендикулярно. Если ты рекламируешь ему цену МЕСЯЦА, то никаким образом клиент у тебя не может простым методом рассчитать цену дня, потому что она дробная и зависит.
А если ты рекламируешь цену дня, либо цену 30 дней, либо цену 30.5 дней, это я там не знаю (хотя на самом деле у тебя на сайте написано месяц, я 100% уверен), то цена дня конечно считается, но появляется вот этот клинический пример про 4-е число и "раньше же хватало".
Мой пример биллинга снимает все эти вопросы. Хочешь - задавай цену дня. Только желательно потом не писать на сайте, что есть цена в месяц.
Хочешь - задавай цену в месяц. Тогда цена дня будет вычисляться хитрожопо, но пример про 4-е число будет обрабатываться правильно одинаково и в голове у клиента, и в биллинге.
При этом желание клиента класть туда ровно 100 рублей через автомат оплаты например перпендикулярно обсуждаемому абсолютно.
Ну и конечно, на то в моем биллинге и возможность расчета с точностью до дня. что иди меняй тариф в любой момент.
Reply
Reply
Leave a comment