Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Не правильно работает MonthsBetween [D7, WinXP]


Страницы:   1 2 3 4

kyn66 ©   (2009-02-06 11:42:00) 

Добрый день. Использую RX компонент function MonthsBetween(Date1, Date2: TDateTime): Double;
Впервые пришлось его применить . Однако после применения обнаружил неверно выдаваемые результаты. Вот оригинальная функция:

function MonthsBetween(Date1, Date2: TDateTime): Double;
var
 D, M, Y: Word;
begin
 DateDiff(Date1, Date2, D, M, Y);
 Result := 12 * Y + M;
 if (D > 1) and (D < 7) then Result := Result + 0.25
 else if (D >= 7) and (D < 15) then Result := Result + 0.5
 else if (D >= 15) and (D < 21) then Result := Result + 0.75
 else if (D >= 21) then Result := Result + 1;
end;


У меня разница в датах 22 дня. Т.е. по идее функция перемещается на строку else if (D >= 21) then Result := Result + 1; и получается на выходе 1. Т.е. разница в датах = 1 мес. Это в корне неверно. 22 дня и 2 мес. Почему так? В чем дело? Как лечить?


kyn66   (2009-02-06 15:04:00) [41]


> А ты уверен, что она правильно работает?

Да мне не нужна точность до миллисекунд. Просто нужно было знать разницу в датах и перевалила-ли разница за месяц и только. Для чего изначально и была попытка применить функцию MonthsBetween. Сравнивать по дням тоже неплохая альтернатива.

> Т.е. идею ты видишь, понимаешь логику этой идеи, но не согласен
> с результатами применения логики.

Может не стоит уже так глубоко заумно высказывать. То с чем я не согласен - я описал. Да и в этой функции идет простой перебор диапазона числа по условиям. И что тут странного, что указанные диапазоны не подходят по условию 22, да возьми любое числ > 21 и < 30 уже получишь на выходе 1. Ну и как это можно считать месяцем? Да.... это или очень заумно или... олдно из трех...


han_malign   (2009-02-06 14:39:00) [42]


> Мне кажется , что 24-2 всегда было =22 и 22 меньше 30(что равно дням в 1 мес)

29 "меньше 30(что равно дням в 1 мес)", значит, по Вашей логике, с 01.02.2009 по 02.03.2009 - прошло 0 месяцев...

З.Ы. Если Вы скажете, что февраль это частный случай, то уже заранее Вам отвечу - каждый год и каждый месяц - это частный случай. А учитывая разницу между юлианским, григорианским и другими( http://ru.wikipedia.org/wiki/%D0%9A%D0%B0%D0%BB%D0%B5%D0%BD%D0%B4%D0%B0%D1%80%D1%8C) календарями...

> Может в математике произошла революция и я пропустил этот момент...

- таки да, пропустил - блок if ...;в MonthsBetween - это классическая характеристическая функция нечеткого множества...
http://ru.wikipedia.org/wiki/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B0%D1%8F_%D0%BB%D0%BE%D0%B3%D0%B8%D0%BA%D0%B0


Anatoly Podgoretsky   (2009-02-06 14:24:00) [43]

Твои ожидания не соответствуют реализации.


Сергей М.   (2009-02-06 14:18:00) [44]


> Значит функция MonthsBetween, будем считать, мне не подходит


Это было ясно изначально, даже при беглом взгляде на код, имея перед носом авторское его описание.


> Пусть авторы подумают, правильно-ли они описали ее назначение
> с ее работой


Описание соответствует реализации.
Чем ты по-прежнему недоволен - совершенно непонятно.


Ega23   (2009-02-06 14:16:00) [45]


> А ты уверен, что она правильно работает?

Немного не то хотел сказать. Работает она так, как в хелпе описано. Вопрос в том, что хочешь получить именно ты.


Ega23   (2009-02-06 14:15:00) [46]


> и правильно работающий в данной ситуации метод DaysBetween


А ты уверен, что она правильно работает?
Что она выдаст на входящие 01.01.2008 00:00:00.000 и 01.01.2008 23:59:59.999 ?
Что она выдаст на входящие 01.01.2008 23:59:59.999 и 01.02.2008 00:00:00.000 ?

В первом случае прошло сутки минус одна миллисекунда.
Во-втором - просто одна миллисекунда.

Со временем вообще всё не так просто. Время - штука в жизни непрерывная. А тут - дискретная. И поведение всех этих функция в приграничных условиях - штука весьма тонкая.


kyn66   (2009-02-06 14:08:00) [47]

>Ega23
Спасибо. Приятно было почитать коммент культурного и грамотного человека.

Больше чем то, что выдает функция в реале я не увижу, а посему оставлю эту функцию в покое и применю подходящий и правильно работающий в данной ситуации метод DaysBetween

Значит функция MonthsBetween, будем считать, мне не подходит. Пусть авторы подумают, правильно-ли они описали ее назначение с ее работой.

Вопрос закрыт, всем спасибо!!!


Ega23   (2009-02-06 13:56:00) [48]

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

1. Как минимум тебя должен был насторожить возвращаемый результат. Ты хочешь получить челое число, а получаешь - реальное.
2. ЕМНИП, Rx ребята писали изначально применительно к банковско-бухгалтерской сфере деятельности. Так что вполне возможно, что с точки зрения бухгалтерии данная функция вполне имеет ссакральный смысл.
3. Если же тебя не устраивает ни Rx.MonthBetween, не родная MonthBetween (с ней тоже не всё просто, в хелп заглянуть не забудь), то никто тебе не мешает написать свою функцию.

Но для этого сначала возьми бумажку и точно распиши весь алгоритм.
Сколько месяцев разница между 01.01.2008 и 31.01.2008? Сколько разница между 31.01.2008 и 01.02.2008? Сколько разница между  01.01.2008 00:00:00 и 31.01.2008 23:59:59.999?

Вот когда ты всё это распишешь и прочитаешь хелп по функциям (это навскидку, я алгоритм не продумывал) DecodeDate\DecodeDateTime, Trunc, IsLeapYear, то написать функцию тебе не составит труда.

А если ты ещё её потом в открытый доступ выложишь, то тебе потом люди спасибо скажут.


Сергей М.   (2009-02-06 13:38:00) [49]


> kyn66 ©   (06.02.09 13:32) [14]


Это ты самсказал:


> по идеефункция перемещается на строку else if (D >= 21)
> then Result := Result + 1; и получается на выходе 1


Т.е. идею ты видишь, понимаешь логику этой идеи, но не согласен с результатами применения логики.

Получается, в [7] истинная правда, как тебе это ни неприятно)


Sergey13   (2009-02-06 13:36:00) [50]

> [14] kyn66 ©   (06.02.09 13:32)
> Это типа прикол, что-ли?

Почему? Я так думаю, что в некоторых областях бухгалтерии это вполне правдоподобный случай.


kyn66   (2009-02-06 13:32:00) [51]


> финансов Узбекской ССР от 13.11.1954 года, в котором четко
> говорится, что после 21 числа в военное время наступает
> новый месяц.

Это типа прикол, что-ли?

> Сергей М.
Судя по приведенному тобой коду и вводимым тобой исх.данным,
>  результат соответствует ожидаемому

Может в математике произошла революция и я пропустил этот момент...
Мне кажется , что 24-2всегда было =22и 22 меньше 30(что равно дням в 1 мес)


Sergey13   (2009-02-06 13:23:00) [52]

> [9] kyn66 ©   (06.02.09 13:09)
> должна правильно работать.

Работа с датами вообще окружена ореолом туманностей. Например сколько дней в месяце?
А в некоторых областях человеческо деятельности на эти туманности могут накладываться еще и какие либо искажающие факторы, типа письма министерства финансов Узбекской ССР от 13.11.1954 года, в котором четко говорится, что после 21 числа в военное время наступает новый месяц.

Так что для решения твоей проблемы необходимо точно условиться что есть "правильно" и что "НЕ правильно".


kyn66   (2009-02-06 13:20:00) [53]


> Какие такие "22 дня и 2 мес

2 мес - очепятка.  Правильно - 1 мес. Плохо что на форуме нет фозможности подкорректировать свой пост.


Declaration
function MonthsBetween(Date1, Date2: TDateTime): Double;
Description
Функция вычисляет число месяцев между двумя датами. Целая часть результата составляет число полных месяцев между двумя датами, дробная часть вычисляется с точностью до 0.25, то есть до недели. Порядок следования аргументов не имеет значения.


При разнице 22 дня ПОЧЕМУ

Result := 12 * Y + M; // = 0
...
else if (D >= 21) then Result := Result + 1


Почему в разнице 22 дня функция говорит, что разница 1 мес. Какое нафик округление?


Сергей М.   (2009-02-06 13:14:00) [54]


> kyn66 ©   (06.02.09 13:09) [9]



> Может такой умный и решит, что 22 дня это и есть месяц ?
>  


Умные документациючитают, прежде чем делать какие-то выводы.
Ты ее к упомянутому методу читал ? Не читал.
Чему же обижаешься ?


Сергей М.   (2009-02-06 13:11:00) [55]


> kyn66 ©   (06.02.09 12:50) [6]


> На выходе получаю 1


Правильнополучаешь.
Судя по приведенному тобой коду и вводимым тобой исх.данным, результат соответствуетожидаемому
Чего тебе еще надо-то ? Какие такие "22 дня и 2 мес" ты увидел и где увидел ?
Чудо)


kyn66   (2009-02-06 13:09:00) [56]


> Вы шо, уважаемый, дурачком прикидываетесь ?

Я попросил-бы...
Может такой умный и решит, что 22 дня это и есть месяц ? А я считаю, что функция если и написана - должна правильно работать. Как выход была пременена фунция DaysBetween. Если умных советов нет кроме оскарблений - тему можно закрыть!!!


Jeer   (2009-02-06 13:03:00) [57]

P.S.
Выцкини все эти if-ы и будет тебе счастье


Jeer   (2009-02-06 13:02:00) [58]


> kyn66 ©   (06.02.09 12:50) [6]


Вы шо, уважаемый, дурачком прикидываетесь ?
Это получается отменно.
Неужели непонятно, что функция работает с округлением ?
Т.е. 22 дня  и более считаются за месяц.


kyn66   (2009-02-06 12:50:00) [59]

Для проверки были взяты два компонента TDateEdit . В один введена дата 02.09.2008во второй   24.09.2008. Затем для проверки вывожу результат

 ShowMessage(FloatToStr(MonthsBetween(DateEdit1.Date, DateEdit2.Date)));


На выходе получаю 1, т.к. кол-во дней между этими датами = 22

У меня разница в датах 22 дня. Т.е. по идее функция перемещается на строку else if (D >= 21) then Result := Result + 1; и получается на выходе 1


22 дня меньше чем 1 мес


Сергей М.   (2009-02-06 12:27:00) [60]


> 1. Т.е. разница в датах = 1 мес. Это в корне неверно. 22
> дня и 2 мес


Выглядит как "казнить нельзя помиловать")

Откуда взялись эти "22 дня и 2 мес", если результат функции имеет тип double?

Ты приведи значение результата в том типе, к котором он объявлен, а не интерпретируй его по-своему ..


Страницы:   1 2 3 4

Наверх

Титульная страница Поиск, карта сайта Написать письмо