1. C# / Говнокод #14140

    +143

    1. 1
    2. 2
    3. 3
    4. 4
    double numberOfDays = (eventWrite.EndDate - eventWrite.StartDate).Days;
    int numberOfSteps = (int)numberOfDays / 365;
    if (numberOfDays / 365 % 4.0027397260273974 == 0)
                numberOfSteps++;

    Сколько раз повторится ежегодное событие с учётом високосного года

    Запостил: SUDALV, 26 Ноября 2013

    Комментарии (47) RSS

    • Замечу, что код работает безупречно )
      Ответить
      • До поры, до времени.
        Ответить
      • емнип, каждый 100й, не являющийся 400ым же не високосный => относительная ошибка порядка .00002
        Ответить
        • Ну вот в 2400 забагует :) Или в 2100? Лень думать, учтена там сотня или только четверка.
          Ответить
          • В 2100м.
            Ещё есть ежегодное событие, происходящее 29 февраля.
            Ответить
          • 4ка учтена тут очень странным образом, 3 и 4 строки вносят погрешность каждые 4 года на 1 день, зато для периода в 368 (или 368+4, если за 368 лет не наберётся) лет единица (из инкремента) компенсирует (вроде бы) кривую компенсацию 4ки.
            Хотя, тогда в 2100м и 2400м будет работать так же, как и в остальные.
            Если считать, что високосный - это раз в 4 года, разница компенсации невисокосных годов 100 лет (вроде бы) набежит где-то за 365*100 лет.
            Ответить
            • предполагалось, что больше 7 лет разницу дат юзер задавать не будет ))
              (но в итоге исправили на нормальный код)
              Ответить
    • си шарп обганяет жавку. жавка не популярна.

      numberOfDays / 365 % 4.0027397260273974 == 0 ниче так,
      хотя проще нада быть , проще
      Ответить
      • ну просто дело было вечером в пятницу, потом сделал по нормальному )
        Ответить
    • Я-нихуя-не-понел.jpg
      Ответить
      • Вот-вот. Очевидно, откуда берётся 4.0027397260273974, но вот что за numberOfSteps, который увеличивается на 1, если прошло ровно 4N лет?
        Ответить
        • >Очевидно, откуда берётся 4.0027397260273974
          Мне - нет.
          Ответить
          • 4 + 1/365
            Ответить
            • numberOfDays / 365 - int же, нет? Остаток от деления целого на нецелое не будет 0. Я молчу уже про ставнение флоатов.
              Ответить
              • > numberOfDays / 365 - int же, нет?
                Нет. Т.к. double numberOfDays.

                > Я молчу уже про ставнение флоатов.
                Да ладно сравнение... Там еще и остаток от деления чисел с плавающей точкой считают...
                Ответить
                • А, это я с numberOfSteps перепутал.

                  Асло, мне очень сильно кажется, что кто-то не осилил модуль работы с календарем... Скажите, в СНГ на уроках программирования все еще учат вручную високосные годы считать?

                  >Там еще и остаток от деления чисел с плавающей точкой считают...
                  Ну а че, работает же, в отличие от сравнения с 0.
                  Ответить
                  • модуль работы с календарём тут не причём, это бекенд. А вот с DateTime да. Ну там уже давно нормально написано.
                    for (var i = eventWrite.StartDate; i <= eventWrite.EndDate; i = i.AddYears(1))
                    Ответить
                    • Под календарем имелось в виду не красивый календарик для юзера, а операции с датами.
                      Ответить
        • numberOfSteps это количество шагов цикла, который следует далее и каждая итерация является очередной записью о будущем срабатывании события. криво выразился. ну какой код такие комментарии ))
          Ответить
          • если итерация <=> запись о событии, то numberOfSteps == количество событий.
            Выходит, для 365*4 - 4 события, 365*4+1 - 5 событий, 365*4+2 - снова 4 события.
            Это я туплю, или код не работает безупречно?
            Ответить
            • ну я проверял разные даты, в том числе на рубеже 29 февраля, вроде всё работало.
              Ответить
            • а откуда возьмётся 365*4 + 2?
              Ответить
              • если прошло 4 года и n дней, есть вероятность, что numberOfDays будет 365*4 + (n+1).
                соответственно, numberOfSteps будет 4, если n != 0, n < 364
                Ответить
                • хм, и остаток от деления соответственно будет не ноль...
                  странно, толи я какой-то код потерял, толи туплю...
                  я уже точно не помню, возможно просто там всегда дата конца и дата начала отличались только годом... в ближайшие дни постараюсь уточнить и отписать сюда )
                  Ответить
                • ааа так стоп, а почему количество шагов должно быть 5? Нам же надо не просто "если наступил следующий год", а чтобы прошло х полных лет от даты первого события
                  Ответить
                  • Сформулируй задачу.
                    Ответить
                    • Посчитать, сколько раз сработает событие, если задана дата А и дата Б, при этом событие должно происходить ежегодно.
                      То есть дата конца не обязательно означает срабатывание события. Логично делать дату А и Б, отличающуюся только годом, но в данном случае пользователю дана свобода
                      Ответить
                      • Ну так найди модуль работы с календарем и посмотри нет ли чего-то там (разницы в годах).
                        Ответить
                        • я же выше уже описал, что сделал и даже как. (заголовок цикла привёл)
                          Ответить
                          • Ну и молодец. А разницы в годах нету? Кстати, а что там с 29 февраля?
                            Ответить
                            • ну с 29 февраля очень просто. например событие охватывает только один високосный год.
                              значит в бд будут записаны подсобытия каждый год 29 февраля, но срабатывать они всё равно не будут.
                              Хотя, .NET наверно не даст создать DateTime с 29 февраля в неправильный год.
                              вообще, спасибо, потестирую
                              Ответить
                              • >Хотя, .NET наверно не даст создать DateTime с 29 февраля в неправильный год.
                                Год прибавить даст.
                                Ответить
                  • Должно быть 4, действительно.
                    Но, судя по коду, для 4N лет, точнее - для (3*365+366)*N дней numberOfSteps будет равным 4N+1.
                    При этом, для (3*365+366)*N + n будет 4N для малых n.
                    Ответить
                    • да, похоже тут всё таки баг ) степс++ в любом случае один раз произойдёт. По-моему было решено, что юзеру нафик ненадо таки большие интервалы дат делать )))
                      (если кто ещё не понял - код писался в полу-шутку, не могли сразу понять как надо, написали чтоб работало, а потом на следующий день написали нормально и зарегистрировались на говнокоде)
                      Ответить
    • Что есть "остаток по модулю вещественного числа"?
      Ну хорошо, я примерно понимаю, что это, но только моё понимание не стыкуется с "==0".
      Например, в моём понимании 1%4.0027 равно 1, а 5%4.0027 равно 0.9973
      Какой-то сишарпобред походу.
      Ответить
      • > Что есть "остаток по модулю вещественного числа"?
        Как интеловский fprem видимо. Он, емнип, так и считает, как ты написал.

        > ==0
        Ну а тут да. Никто не гарантирует, что последний разряд не разойдется.
        Ответить
        • разойдется более чем гарантированно
          Ответить
          • при этой точности работало

            з.ы. если бы это был нормальный код, стал бы я тут его выкладывать?
            Ответить
            • Серьезно работало? Хм.
              Ответить
              • ну мне смысла врать нет )
                Ответить
                • В путхоне

                  1./365 % .0027397260273974
                  0.0027397260273972603
                  Ответить
                  • вот и разошлось
                    от настроек фпу зависит
                    Ответить
                    • ну я специально ничего не настраивал. Обычный IIS8 с ASP .NET 4.5.
                      сейчас просто время проверить нету.
                      Ответить
                    • Так вот для чего в C# есть strfpi или как там его: чтобы говнокод был переносимым!
                      Ответить
                  • 1./365
                    0.0027397260273972603
                    vs
                    0.0027397260273974
                    Ответить
              • Так там оно не работает, либо если период - ровно 4N лет (с точностью до дня), либо если период больше 365 лет (или 365*4 лет), и накопилась разница из-за того, что разделили на 365, либо из-за нецелого количества лет будет единица гулять (но им это не надо).
                Ответить
    • Я, расстроенный и озадаченный последним поцелуем, побрел домой.
      Ответить

    Добавить комментарий