Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2009.03.29;
Скачать: [xml.tar.bz2];

Вниз

Не правильно работает MonthsBetween   Найти похожие ветки 

 
kyn66 ©   (2009-02-06 11:42) [0]

Добрый день. Использую 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 мес. Почему так? В чем дело? Как лечить?


 
Сергей М. ©   (2009-02-06 11:59) [1]


> Использую RX компонент function MonthsBetween


Это что,так компонент называется ?
Или это метод какого-то оригинального класса из RXLib ?


 
kyn66 ©   (2009-02-06 12:07) [2]

>Сергей М
Ну мастер такого класса мог догадаться, что это опечатка была, ессно метод. Я думаю дальше будем по делу обсуждать? ;)


 
Сергей М. ©   (2009-02-06 12:10) [3]


> дальше будем по делу обсуждать?


Будем, если ты приведешь оригинальный текст всего того, что скрывается за DateDiff, а также конкретные Double-значение, которые ты передаешь вх.параметрами в метод MonthsBetween


 
Jeer ©   (2009-02-06 12:22) [4]


> Однако после применения обнаружил неверно выдаваемые результаты.


Это с твоей точки зрения.
Напиши свою - "правильную" реализацию.
Там все прозрачно.


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


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


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

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

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


 
kyn66 ©   (2009-02-06 12:50) [6]

Для проверки были взяты два компонента 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 мес


 
Jeer ©   (2009-02-06 13:02) [7]


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


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


 
Jeer ©   (2009-02-06 13:03) [8]

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


 
kyn66 ©   (2009-02-06 13:09) [9]


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

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


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


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


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


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


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


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



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


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


 
kyn66 ©   (2009-02-06 13:20) [12]


> Какие такие "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 мес. Какое нафик округление?


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

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

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

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


 
kyn66 ©   (2009-02-06 13:32) [14]


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

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

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

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


 
Sergey13 ©   (2009-02-06 13:36) [15]

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

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


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


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


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


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


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

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


 
Ega23 ©   (2009-02-06 13:56) [17]

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

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, то написать функцию тебе не составит труда.

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


 
kyn66 ©   (2009-02-06 14:08) [18]

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

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

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

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


 
Ega23 ©   (2009-02-06 14:15) [19]


> и правильно работающий в данной ситуации метод 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 ?

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

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


 
Ega23 ©   (2009-02-06 14:16) [20]


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

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


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


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


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


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


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


 
Anatoly Podgoretsky ©   (2009-02-06 14:24) [22]

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


 
han_malign ©   (2009-02-06 14:39) [23]


> Мне кажется , что 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


 
kyn66 ©   (2009-02-06 15:04) [24]


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

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

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

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


 
Jeer ©   (2009-02-06 15:10) [25]


> Да мне не нужна точность до миллисекунд


Тебе.


> Да.... это или очень заумно


Но это ведь не наша проблема, а твоя ?


 
kyn66 ©   (2009-02-06 15:12) [26]

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


 
Jeer ©   (2009-02-06 15:14) [27]

Что же касается твоих претензий к данной реализации - твоим потокомыслям хан_малигн придал правильное направление ( нечеткая логика )

Добавлю англоязычное звучание, если с русским плохо - Fuzzi logic

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


 
Johnmen ©   (2009-02-06 15:15) [28]


> да возьми любое числ > 21 и < 30 уже получишь на выходе
> 1. Ну и как это можно считать месяцем?

Легко, если это февраль.

ЗЫ
Короче, персонально для тебя поднятая тема очень заумна. Поэтому считай, что месяц=30 и живи спокойно. Но НИКОГДА не претендуй на профессию программиста. И на другие, связанные с элементарной логикой и математикой, тоже.
Это не наезд, а добрый совет по жизни...


 
Jeer ©   (2009-02-06 15:17) [29]


> и решаем ее вместе,


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


 
Ega23 ©   (2009-02-06 15:19) [30]


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


Блин. Ещё раз:
Перевалила ли разница в датах 01.01.2008 и 01.02.2008 (31 "сутки") за месяц?
Перевалила ли разница в датах 01.02.2008 и 01.03.2008 (29 "суток") за месяц?
Перевалила ли разница в датах 01.02.2009 и 01.03.2009 (28 "суток") за месяц?
Перевалила ли разница в датах 17.02.2009 и 17.03.2009 (28 "суток") за месяц?

Ты пойми, чёткого алгоритма нет. Т.к. нет абсолютно чёткого понимания, что такое "месяц".


 
Jeer ©   (2009-02-06 15:21) [31]


> Т.к. нет абсолютно чёткого понимания, что такое "месяц".


А если сюда еще подключить ОТО и СТО - а даже не представляю, чем все это закончится :)


 
Sergey13 ©   (2009-02-06 15:23) [32]

> [24] kyn66 ©   (06.02.09 15:04)
> да возьми любое числ > 21 и < 30 уже получишь на выходе 1. Ну и как это можно считать месяцем?

1. 28 и 29 вполне реально соответствуют месяцу.
2. Я ж тебе говорю, что в военное время косинус 45 градусов может доходить до 3-х. 8-)
3. Ну например, могу ли я внести платеж по кредиту не 10 (как в договоре например), а 5 числа или 15? Данная функция вполне резонно ответит что могу. Так как разница между этими числами и номинальным числом платежа практически нулевая, т.е. <7. Что тут нелогичного? Значит функция правильная.


 
Anatoly Podgoretsky ©   (2009-02-06 15:32) [33]

> Sergey13  (06.02.2009 15:23:32)  [32]

Дурные бухгалтера считают в месяцах, а умные в сутках и никогда не ошибатся, поскольку 30 дней они и в Африке 30 дней.


 
kyn66 ©   (2009-02-06 15:33) [34]


> Легко, если это февраль.

Это исключение. Вопрос в принципе.


> Но НИКОГДА не претендуй на профессию программиста. И на
> другие, связанные с элементарной логикой и математикой,
> тоже.

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


 
Ega23 ©   (2009-02-06 15:45) [35]


> Это исключение. Вопрос в принципе.


Да пойми ты одну простую вещь: понятие "месяц назад" или "через месяц" зависит от текущей даты (про всякие сдвиги по времени, часовые пояса, различные "летоисчисления" я сейчас вообще молчу).
Сегодня у нас 6 февраля. "Месяц" назад, например, было 6 января. Прошёл 31 день.
Через "месяц" будет 6 марта. Пройдёт 28 дней. А если ещё точнее, то пройдёт 27 дней, 8 часов и 15 минут, т.к. я не строго в полночь спрашиваю.


 
Ega23 ©   (2009-02-06 15:48) [36]

И обижаешься ты зря. Тебе пытаются объяснить, что то определение, которое ты пытаешься вытащить - оно бессмысленно. Точнее, вполне возможно, что оно тебе для каких-то нужд и нужно, но само по себе оно, как ты его себе представляешь, в корне не верно.
А ты как баран упёрся и понять не желаешь.


 
Johnmen ©   (2009-02-06 15:50) [37]


> А это уж, извени , не тебе судить и решать.

Конечно не мне! Я и не решаю, а даю совет, как избежать того, когда тебе станет мучительно больно.
Следовать моим, или чьим бы то ни было советам, вовсе не обязательно. Но кто внемлет, то предупрежден, а значит вооружен...


 
Anatoly Podgoretsky ©   (2009-02-06 15:50) [38]

> Ega23  (06.02.2009 15:48:36)  [36]

Пятница и тяжелое прошлое.


 
kyn66 ©   (2009-02-06 15:52) [39]


> Ну например, могу ли я внести платеж по кредиту не 10 (как
> в договоре например), а 5 числа или 15? Данная функция вполне
> резонно ответит что могу. Так как разница между этими числами
> и номинальным числом платежа практически нулевая, т.е. <7

Не совсем уместныйй пример и причем здесь фигурирует число 7? Кредит когда хочу - тогда и вношу, конечно стараюсь в срок. А кто нибудь сделал акцент на то, почему у функции MonthsBetween на выходе не Integer, а Double? Целая часть результата составляет число полных месяцев между двумя датами, дробная часть вычисляется с точностью до 0.25, то есть до недели. А почемц именно 0.25? Да потому, что в месяце 4 недели.

Если у меня разница в днях 22. Так почему-же функция мне не выдает на выходе дробное число, типа 0.68 , а 1. Я еще раз говорю, причем здесь округление?

Она должна мне реально сказать, что ваше число 22 меньше , чем 30(примем за кол-во дней в месяце) , на выходе 0.68. А так как я сравниваю выходное значение функции с 1(месяц), то убеждаюсь, что моя разница меньше месяца. Ну и что тут сложного? Зачем в дебри логарифмические лезть?


> номинальным числом платежа практически нулевая, т.е. <7.
>  Что тут нелогичного?

А почему не 8, не 9, не 10???

Просто в этой функции решили совместить двойной ответ. Только зачем недели прикрутили? .... Может кому и надо. Иногда название функции в большей мере отвечает за свое назначение. Поэтому в первую очередь ее и рассматриваешь.


 
Sergey13 ©   (2009-02-06 15:59) [40]

> [39] kyn66 ©   (06.02.09 15:52)
> А почемц именно 0.25? Да потому, что в месяце 4 недели.

Кто тебе сказал? Это в феврале только. В январе 4 недели и 3 дня. А 3 дня это уже половина недели почти.

> Она должна мне реально сказать

Т.е. ты автору заплатил, дал задание, он написал а она не говорит? Безобразие. Я вот тоже хотел MP3 файл на слова порезать, а WORD мне этого не смог сделать. Мелкомягким что ли нажаловаться?

> Просто в этой функции решили совместить двойной ответ.
Решили потому, что так АВТОРАМ было нужно.

> Только зачем недели прикрутили?
Это твои домыслы.

> Иногда название функции в большей мере отвечает за свое
> назначение. Поэтому в первую очередь ее и рассматриваешь.
Умоляю, не пей водку Путинка. Путин у нас уже есть один и второму не бывать!!!



Страницы: 1 2 вся ветка

Форум: "Начинающим";
Текущий архив: 2009.03.29;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.57 MB
Время: 0.045 c
1-1208160317
@!!ex
2008-04-14 12:05
2009.03.29
Проверка корректности файла


15-1233319858
istok
2009-01-30 15:50
2009.03.29
D2009 перестала запускаться...


15-1233131001
Palladin
2009-01-28 11:23
2009.03.29
Работа программ на Delphi 2009


15-1232538759
SPeller
2009-01-21 14:52
2009.03.29
ICQ таки обломало сторонних клиентов?


2-1233348637
Тимоха
2009-01-30 23:50
2009.03.29
класс TThread и api





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский