(Untitled)

Nov 09, 2014 01:51

Случился спонтанный ликбез по поводу float-ов в биллинге:

http://amarao-san.livejournal.com/2944300.html

То, что программисты через одного не понимают, что такое плавающая точка и какой физический смысл расчетов в ней, это вымораживает конечно каждый раз.

it/tech

Leave a comment

dmih November 9 2014, 00:33:19 UTC
Ты прицепился к какой-то вот этой своей "списание посуточное". Нет, не посуточное.
Расчет посуточный. А списание как надо.

Алгоритм простой. Цена задается за период. Период состоит из месяцев и дней. Годы не нужны, т.к. год всегда 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

ufm November 9 2014, 01:01:54 UTC
Дим, ты описываешь отличный алгоритм. Пока к тебе не приходит абонент и не спрашивает "а сколько мне надо заплатить, что-бы на 3 дня хватило" и платит (с точностью до копейки, сука) за услугу, цена на которую указана за месяц. Если думаешь что я утрирую - ты заблуждаешься.

Именно по этому у нас для юриков оплата помесячная (все равно они по договору раз в месяц платят) а для физиков - посуточная (и нету больше проблемы ему объяснять что за 31 января ему надо заплатить столько, а за 1 февраля - вот столько).

А уж если юрик разорвёт договор в середине месяца - бухгалтерия уж как нибудь ему на калькуляторе посчитает сколько надо оплатить а сколько вернуть.

Reply

dmih November 9 2014, 01:08:07 UTC
В описанном алгоритме это решается очень просто - задается период 0 месяцев 1 день, пишется туда цена в копейках, как ты хотел, и вперед. И он будет тогда фигачить списания по дням. И цена дня будет одинаковая.
Он в этом смысле полностью универсален. Но при этом можно также честно писать месячную цену, и годовую цену.
Это не другой алгоритм. Это просто нормальный полноценный алгоритм, который любым раком потом можно поставить и он будет считать правильно. Правильный подневный расчет при необходимости - его подмножество.

Reply

ufm November 9 2014, 01:14:42 UTC
Ты меня сейчас в чём убеждаешь? В том, что твой алгоритм правильный или в том, что флоат кошерен и полезен?

Если первое - не надо, я тебе на слово верю (тем более проверять - уже голова не варит, а ты утверждаешь что ты им пользуешься, т.е. он как минимум "проверен временем").

Если второе - тоже не надо. Вот тебе выдержка из нашей переписки с 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

dmih November 9 2014, 01:24:25 UTC
Не ну это понятно, избегание сложностей сильным запретом функционала. На самом деле если сработало, то удачный подход.

Reply

dmih November 9 2014, 01:25:52 UTC
А пример был про то, что там таки нужен float.

Reply

dmih November 9 2014, 01:26:15 UTC
Или его эмуляция.

Reply

ufm November 9 2014, 01:34:24 UTC
Там другая беда.
В декабре и январе 31 день. 124/31 - 4 рубля в день.
В феврале - 28. - 4.42 в день (4.428571429, если в любимом тобой флоате, но это не важно).
Абонент заплатил 4 января 124 рубля, из расчёта, что ему хватит до 4 февраля (он же платил 4-го декабря, и ему хватило!!!!!1111адинадин)
А на самом деле.
124-28*4= 12
Т.е. ему в феврале 12 рублей не хватит на 3 дня хоть с флоатом хоть без.

Reply

dmih November 9 2014, 01:37:37 UTC
Ты неверно применил мой алгоритм. Цена расчитывается не исходя дней в месяце, а дней в периоде, в его случае с четвертых чисел.

Reply

dmih November 9 2014, 01:39:00 UTC
Т е с 4 го по 4 е цена одинаковая всегда, в этом же суть метода.

Reply

ufm November 9 2014, 01:44:41 UTC
Это ты неправильно понял. У него не "пирод с 4 по 4". У него вообще нет периода. Это-ж физик. Он деньги платит - ка бог на душу положит. Школьник на обедах сэкономил и на 3 дня себе интернет решил включить.

P.S. Я торгую интеренетом, если чо. Т.е. не хостингом. :)

Reply

dmih November 9 2014, 01:49:43 UTC
Ты перечитай еще раз тредик завтра, ты просто запутался имхо. Я тебя понял прекрасно, а ты все время считаешь своим алгоритмом и говоришь, что мой не прав, хотя надо что то одно.

Reply

ufm November 9 2014, 01:53:46 UTC
Сначала надо полностью ТЗ описать, что-бы непоняток небыло. Вот скажи мне, оно нам, двум взрослым дядькам, надо? С учетом того, что это чисто умозрительный эксперимент - ни я биллинг переделывать не буду, так как меня всё устраивает, ни ты, по той-же причине. :)

Reply

ufm November 9 2014, 02:03:00 UTC
Да, скорее всего мы с тобой друг-друга не понимаем знаешь по какой причине? Потому что тот-же физик чаще всего платит не за "30 дней интернета", а "положите мне на счёт 100 рублей".

Мало того, абонент может менять тариф среди месяца.

Т.е. у меня нет возможности расчитывать стоимость периода. Только стоимость 1 дня. А тут как не крути - (стоимость тарифа в месяц)/(дней в месяце).

Reply

dmih November 9 2014, 02:17:49 UTC
Смотри, суть простая.

Либо ты указываешь на сайте цену дня, либо указываешь на сайте цену месяца.

Если цену дня, то разговор можно закрыть. Всё просто предельно. Или цену 30 дней, что оно и то же.

Либо ты указываешь цену месяца.
Либо - что ты 5-й раза уже пишешь в примерах - ты указываешь цену 30 дней а ТВОЙ (не мой!) клиент думает, что это цена месяца. Вот эти вот твои примеры постоянные про 4-е число и раньше хватало !!!адынадын - это от того, что ты выставил цену ДНЯ, а клиент её понял как МЕСЯЦА.
Потому что месяца, вообще-то, логичнее.
И в рекламе у вас поди не дни указаны, а месяцы всё-таки.

И вот твой клинический пример про 4-е числа и желание клиента "раньше же хватало" - мой биллинг - решает. Если раньше хватало, то хватит и сейчас.
Твой - нет.

Вот собственно и всё.

При этом, желание клиента класть туда произвольные суммы перпендикулярно. Если ты рекламируешь ему цену МЕСЯЦА, то никаким образом клиент у тебя не может простым методом рассчитать цену дня, потому что она дробная и зависит.
А если ты рекламируешь цену дня, либо цену 30 дней, либо цену 30.5 дней, это я там не знаю (хотя на самом деле у тебя на сайте написано месяц, я 100% уверен), то цена дня конечно считается, но появляется вот этот клинический пример про 4-е число и "раньше же хватало".

Мой пример биллинга снимает все эти вопросы. Хочешь - задавай цену дня. Только желательно потом не писать на сайте, что есть цена в месяц.
Хочешь - задавай цену в месяц. Тогда цена дня будет вычисляться хитрожопо, но пример про 4-е число будет обрабатываться правильно одинаково и в голове у клиента, и в биллинге.

При этом желание клиента класть туда ровно 100 рублей через автомат оплаты например перпендикулярно обсуждаемому абсолютно.

Ну и конечно, на то в моем биллинге и возможность расчета с точностью до дня. что иди меняй тариф в любой момент.

Reply

dmih November 9 2014, 01:50:37 UTC
Твоему флоаты не помогут и не нужны.

Reply


Leave a comment

Up