Контакти

Скільки місяців пройшло між двома датами. Як однією математичною формулою за номером місяця порахувати кількість днів у ньому? Скільки днів між датами? Інструкція

Примітка: Даний пост є перекладом статті cmcenroe.me/2014/12/05/days-in-month-formula.html ( частина I), А також авторським до нього доповненням ( частина II). Не слід ставитися до матеріалу серйозно, а скоріше як до розминки для розуму, що вимагає не більше ніж шкільних знань арифметики і не має практичного застосування. Всім приємного читання!

частина I

вступ

Нещодавно, після чергової безсонної ночі, я розмірковував про методи запам'ятовування кількості днів у кожному місяці року. Для цього є лічилки, а також спосіб вважати на кісточках пальців, але ні те, ні інше мене не влаштувало. Я задумався, а чи не існує якоїсь математичної формули для вирішення такого завдання, і - не знайшовши при побіжному вивченні таку - кинув собі виклик її створити.

Формалізуючи Іншими словами, необхідно знайти функцію f, Таку, що значення f (x) для кожного місяця x, Представленого числом від 1 до 12, дорівнює кількості днів у цьому місяці. Таблиця значень аргументу і функції:

x 1 2 3 4 5 6 7 8 9 10 11 12
f (x) 31 28 31 30 31 30 31 31 30 31 30 31

Якщо у вас виникло бажання спробувати самому до прочитання мого рішення, то зараз саме час. Якщо ж ви віддаєте перевагу негайно побачити готову відповідь, то подивіться під спойлер.

відповідь


Нижче наведені мої кроки по знаходженню рішення.

математичний апарат

Спочатку побіжно освіжимо в пам'яті два життєво необхідних у вирішенні цього завдання оператора: цілочисельне ділення і залишок від ділення.

цілочисельне діленняце оператор, який застосовується в багатьох мовах програмування при розподілі двох цілих чисел і відкидає від приватного дробову частину. Я буду зображати його як. наприклад:

Залишок від ділення це оператор, що знаходить залишок від ділення. У багатьох мовах програмування застосовується символ % , Я ж буду використовувати конструкції виду, наприклад:

Зауважу, що залишок від ділення має рівний з розподілом пріоритет.

основи

Отже, застосуємо наш математичний апарат для отримання базової формули. У звичайному місяці 30 або 31 день, так що ми можемо використовувати для отримання черзі 1 або 0, а потім просто додати до цього числа константу:

Отримуємо таблицю, напівжирним виділені коректні значення:
x 1 2 3 4 5 6 7 8 9 10 11 12
f (x) 31 30 31 30 31 30 31 30 31 30 31 30

Непоганий початок! Вже є правильні значення для січня і для місяців з березня по липень включно. Лютий - особливий випадок, і з ним ми розберемося трохи пізніше. Після липня для решти місяців порядок отримання 0 і 1 має бути змінений на зворотний.
Для цього ми може додати до делимому 1:

x 1 2 3 4 5 6 7 8 9 10 11 12
f (x) 30 31 30 31 30 31 30 31 30 31 30 31

Тепер правильні значення з серпня по грудень, але, як і передбачалося, значення для інших місяців невірні. Давайте подивимося як ми можемо об'єднати ці формули.

накладення маски

Для цього необхідна кусочно-задана функція, але - так як мені це здалося нудним - я задумався про інший шлях вирішення, що використовує одну частину функції на одному інтервалі, іншу - на іншому.
Вважаю, що найпростіше буде знайти вираз, що дорівнює 1 в одній області застосування і 0 - в решті. Метод, в якому множачи аргумент на вираз ми виключаємо його з формули поза області його застосування, я назвав «накладенням маски», тому така поведінка подібно якоїсь бітової масці.
Для застосування цього методу в останній частині нашої функції необхідно знайти вираз, що дорівнює 1 при, і - так як значення аргументу завжди менше 16 - для цього прекрасно підходить цілочисельне ділення на 8.
x 1 2 3 4 5 6 7 8 9 10 11 12
x ⁄ 8 ⌋ 0 0 0 0 0 0 0 1 1 1 1 1

Тепер за допомогою цієї маски, використовуючи в подільному вираз замість 1, ми можемо замінити порядок отримання 0 і 1 формулою на зворотний:

x 1 2 3 4 5 6 7 8 9 10 11 12
f (x) 31 30 31 30 31 30 31 31 30 31 30 31

Еврика! Все правильно, крім лютого. Сюрприз-сюрприз.

Лютий

У будь-якому місяці 30 або 31 день, крім лютого з його 28 (високосний рік виходить за рамки цього завдання). На поточний момент по нашій формулі в ньому 30 днів, тому непогано б відняти вираз, що дорівнює 2 при.
Найкраще що мені вдалося придумати це, що накладає маску на всі місяці після лютого:
x 1 2 3 4 5 6 7 8 9 10 11 12
2 mod x 0 0 2 2 2 2 2 2 2 2 2 2

Змінивши базову константу на 28 з додаванням 2 до решти місяців отримаємо формулу:

x 1 2 3 4 5 6 7 8 9 10 11 12
f (x) 29 28 31 30 31 30 31 31 30 31 30 31

На жаль, січень тепер коротше на 2 дня. Але, на щастя, отримати вираз, яке буде застосовуватися тільки для першого місяця дуже легко: це округлене вниз зворотне до число. Помноживши його на 2 отримуємо остаточну формулу:

x 1 2 3 4 5 6 7 8 9 10 11 12
f (x) 31 28 31 30 31 30 31 31 30 31 30 31

Післямова

Ось вона - формула для отримання кількості днів у будь-якому місяці року, що використовує найпростішу арифметику. Наступного разу коли ви будете згадувати скільки ж днів у вересні, просто виконайте за допомогою цієї однорядковою функції на JavaScript:

Function f (x) (return 28 + (x + Math.floor (x / 8))% 2 + 2% x + 2 * Math.floor (1 / x);)

частина II

вступ

У першій частині була отримана коротка і навіть трохи витончена формула, основними перевагами якої є простота математичного апарату, відсутність розгалужень і умовних виразів, лаконічність. До недоліків - крім того, що ви не будете застосовувати її в вашому проекті - можна віднести відсутність перевірки на віскокосний і не високосний рік.
Тому я поставив перед собою завдання створити функцію f, Таку, що значення f (x, y) для кожного місяця x, Представленого числом від 1 до 12 і роки y, Більшого 0, дорівнює кількості днів у місяці x в році y.
Для нетерплячих під спойлером знаходиться готову відповідь, інших же прошу слідувати за мною.

відповідь

Залишок від ділення: mod і ⌊⌋

Для візуальної наочності домовимося, що в деяких формулах оператор ділення із залишком замінений нижніми дужками, там де це здалося мені необхідним:

Високосний рік

У високосний рік вводиться додатковий день календаря: 29 лютого. Як відомо, високосним є рік, кратний 4 і не кратний 100, або кратний 400. Запишемо тотожне цього висловлювання вираз:

Для приведення цього виразу в алгебраїчне, необхідно застосувати до результату виразу ін'єкцію виду:

Що дозволить отримати 1 при діленні без залишку і 0 при діленні з залишком, щоб використовувати її у формулі визначення кількості днів у місяці.

В якості опції g " можна використовувати 1 мінус залишок від ділення для:

x 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
g "(x) Infinity 1 0 0 0 0 0 0 0 0 0 0 0 0 0

Легко помітити, що збільшивши ділене і дільник на 1 ми отримаємо правильну формулу при:
x 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
g "(x) 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0

Таким чином вираз запишемо як:


А вираз запишемо як:

Застосовуючи цей підхід отримаємо таку функцію g (y), Значенням якої буде 1, якщо рік високосний, чи 0 в зворотному випадку:

y 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000
g (y) 0 0 1 0 0 0 1 0 0 0 1
y 2000 2100 2200 2300 2400 2500 2600 2700 2800 2900 3000
g (y) 1 0 0 0 1 0 0 0 1 0 0

Напівжирним виділені високосні роки.

Нагадую, що в рамках прийнятої домовленості оператор отримання залишку від ділення може бути зображений як mod, так і ⌊⌋.

накладення маски

У формулі частина є поправкою, яка додає 2 дня до січня. Якщо прибрати множник 2 і в чисельнику замінити 1 на 2, тоді ця формула буде додавати 2 дні до січня і 1 день до лютого, що дає нам ключ до додаванню дня у високосному році. Для наочності використовуємо у формулі проміжне значення g (y) і в якості y використовуємо 2000 (високосний) і 2001 (невисокосному) роки:

x 1 2 3 4 5 6 7 8 9 10 11 12
f (x, 2000) 31 29 31 30 31 30 31 31 30 31 30 31
f (x, 2001) 30 28 31 30 31 30 31 31 30 31 30 30

Значення для всіх місяців, крім січня не високосного року вірні.

Для виправлення цього прикрого непорозуміння додамо до січня 1 день вже відомої нам формулою:


або:

x 1 2 3 4 5 6 7 8 9 10 11 12
f (x, 2000) 31 29 31 30 31 30 31 31 30 31 30 31
f (x, 2001) 31 28 31 30 31 30 31 31 30 31 30 30

висновок

В результаті отримана вже значно більш громіздка, але більш універсальна формула, яку також можна використовувати для отримання кількості днів у місяці певного року:

Function f (x, y) (return 28 + ((x + Math.floor (x / 8))% 2) + 2% x + Math.floor ((1 + (1 - (y% 4 + 2)% (y% 4 + 1)) * ((y% 100 + 2)% (y% 100 + 1)) + (1 - (y% 400 + 2)% (y% 400 + 1))) / x) + Math.floor (1 / x) - Math.floor (((1 - (y% 4 + 2)% (y% 4 + 1)) * ((y% 100 + 2)% (y% 100 + 1 )) + (1 - (y% 400 + 2)% (y% 400 + 1))) / x);)
Приклад на C # ideone.com/fANutz.

1 . Я не вмію користуватися подібною мнемонікою, тому підглянув табличку в інтернеті.
2 . «Основи», або «Правило З Багатьма Винятками», як і більшість правил.
3 . Спочатку в римському календарі лютого був останнім місяцем року, тому є логіка в тому, що він коротше всіх інших. Також є логіка в додаванні або видаленні дня саме в кінці року, тому його довжина є змінною.

Upd. 1:
Альтернативний переклад першої частини в

Безкоштовний онлайн калькулятор Контур.Бухгалтеріі вам допоможе і підкаже, скільки днів минуло між двома заданими датами. Крім того, якщо у вас виникла необхідність, ви можете порахувати скільки календарних, вихідних або робочих днів (годин) містить вказаний період року або декількох років.

Скільки днів між датами? Інструкція

Ви просто задаєте конкретний день початку і кінця і через долі секунд отримуєте розрахунок. Всі дані онлайн-калькулятор вважає самостійно. Якщо ви змінюєте вихідні дні тижня, результат автоматично перераховується, з урахуванням високосного року.

Важливо: не можна брати з розрахунків за минулі роки показники робочих днів / годин за місяць і надавати в якості розрахунків - дані будуть різнитися. Тому, краще скористайтеся калькулятором.

Отже, порядок дій:

  1. В полях "Початкова дата" і "Кінцева дата" обираєте відповідно початковий і кінцевий день відліку, починаючи з 2013 року і закінчуючи в майбутньому 2018 м.
  2. Встановлюєте в наступному полі кількість робочих годин у добі. За замовчуванням в цьому полі вже коштує 8 годин (40-годинний робочий тиждень), але ви можете цю цифру змінити.
  3. У правій частині екрана на банері ви побачите отриманий результат: робочі дні, календарні дні і робочі години між заданими дат. Результати потрібно скопіювати і зберегти в своєму документі.

Для чого можна використовувати калькулятор

  1. Для розрахунку пені і прострочень по договорам
  2. Як зрозуміти ефективність використання якого-небудь ресурсу і граничні терміни використання
  3. Як, бува, не призначити терміни виконання завдання на вихідний день
  4. Скільки часу залишилося до дедлайну

приклад:

Ви - бухгалтер. Керівник попросив вас в найближчі пару хвилин надати дані щодо кількості робочих годин, які повинні відпрацювати всі співробітники компанії в лютому. Кількість працівників ви можете легко визначити - у вас перед очима цифри. А ось кількість годин потрібно вважати .... А скільки там в лютому днів? А рік-то високосний? А які дні були вихідними? А як визначити кількість днів свят?

Рішення: просто скористайтеся нашим віджетом. Всю інформацію ви отримаєте автоматично, вам не потрібні настільні календарі і калькулятори.

Вам сподобався цей калькулятор? Тоді спробуйте інші наші можливості

Хочете вести бухоблік, відправляти звітність і робити розрахунки в зручному і простому веб-сервісі? Спробуйте безкоштовно 14 днів Контур.Бухгалтеріі! Ми швидко вас навчимо, як сервісом користуватися і відповімо на всі питання!

Для вирішення деяких завдань при створенні таблиці потрібно в окремій клітинці або всередині формули вказати кількість днів у місяці, щоб програма провела необхідні розрахунки. У Ексель є інструменти, призначені для виконання даної операції. Давайте розглянемо різні способи застосування даної можливості.

Обчислити кількість днів у місяці в Ексель можна за допомогою спеціальних операторів категорії "Дата і час". Щоб з'ясувати, який саме варіант краще всього застосувати, потрібно, перш за все, встановити цілі виконання операції. Залежно від цього результат обчислення може виводитися в окремий елемент на аркуші, а може використовуватися і всередині іншої формули.

Спосіб 1: комбінація операторів ДЕНЬ і КОНМЕСЯЦА

найбільш простим способом вирішити це завдання є комбінація операторів ДЕНЬ і КОНМЕСЯЦА.

функція ДЕНЬ належить до групи операторів "Дата і час". Вона вказує на конкретне число від 1 до 31 . У нашому випадку завданням даного оператора буде вказівка останнього дня місяці за допомогою вбудованої функції у вигляді аргументу КОНМЕСЯЦА.

синтаксис оператора ДЕНЬ наступний:

ДЕНЬ (дата_в_чісловом_формате)

Тобто, єдиним аргументом даної функції є «Дата в числовому форматі». Його і буде задавати оператор КОНМЕСЯЦА. Потрібно сказати, що дата в числовому форматі відрізняється від звичного формату. Наприклад, дата 04.05.2017 в числовому вигляді буде виглядати, як 42859 . Тому цей формат Ексель використовує тільки для внутрішніх операцій. Він рідко застосовується для відображення в осередках

оператор КОНМЕСЯЦА призначений для того, щоб вказувати порядковий номер останнього дня місяця, який знаходиться на задану кількість місяців вперед або назад від зазначеної дати. Синтаксис функції такий:

КОНМЕСЯЦА (нач_дата; чісло_месяцев)

оператор "Початкова дата" містить дату, від якої починається відлік, або посилання на осередок, де вона знаходиться.

оператор «Число місяців» вказує на ту кількість місяців, на яке слід проводити відлік від заданого числа.

Тепер давайте подивимося, як це працює на конкретному прикладі. Для цього візьмемо лист Excel, В одну з комірок якого вписано певну календарне число. Потрібно за допомогою вказаного вище набору операторів визначити, скільки днів в тому місячному періоді, до якого це число відноситься.


Загальна формула у нас прийняла такий вигляд:

ДЕНЬ (КОНМЕСЯЦА (B3; 0))

У цій формулі змінним значенням є тільки адреса комірки ( B3). Таким чином, якщо ви не хочете виконувати процедуру за допомогою майстри функцій, Можна вставити цю формулу в будь-який елемент листа, просто замінивши адресу комірки, що містить число, на той, який актуальний в конкретно вашому випадку. Результат буде аналогічний.

Спосіб 2: автоматичне визначення кількості днів

Тепер давайте розглянемо іншу задачу. Потрібно, щоб кількість днів виводилося не по заданому календарного числа, а за поточним. До того ж зміна періодів проводилася б автоматично без участі користувача. Хоч це і здається дивним, але дана задача легше попередньої. Для її вирішення навіть відкривати Майстер функцій не потрібно, так як формула, яка виконує дану операцію, не містить змінних значень або посилань на осередки. Ви просто можете вбити в ту клітинку аркуша, де хочете, щоб з'явився результат, наступну формулу без змін:

ДЕНЬ (КОНМЕСЯЦА (СЬОГОДНІ (); 0))

Вбудована функція СЬОГОДНІ, яку ми застосували в даному випадку, відображає сьогоднішнє число і не має аргументів. Таким чином, у вас в осередку постійно буде відображатися кількість днів у поточному місяці.

Спосіб 3: обчислення кількості днів для використання в складних формулах

У прикладах вище ми показали, як виконувати обчислення кількості днів у місяці за вказаною календарного числа або автоматично по поточному місяцю з висновком результату в окрему клітинку. Але знаходження даного значення може знадобитися і для обчислення інших показників. При цьому розрахунок кількості днів буде здійснюватись всередині складної формули і не стане виводитися в окремій клітинці. Подивимося, як це зробити на прикладі.

Нам потрібно зробити так, щоб в осередку відображалося то кількість днів, що залишився до кінця поточного місяця. Як і в попередньому способі, даний варіант дій не вимагає відкриття майстри функцій. Ви можете просто вбити в клітинку такий вираз:

ДЕНЬ (КОНМЕСЯЦА (СЬОГОДНІ (); 0)) - ДЕНЬ (СЬОГОДНІ ())

Після цього в зазначеній комірці буде виводитися число днів до кінця місяця. Кожен день результат буде автоматично оновлюватися, а з початку нового періоду відлік почнеться заново. Виходить своєрідний таймер зворотного відліку.

Як бачимо, зазначена формула складається з двох частин. Перша з них являє собою вже знайоме нам вираз розрахунку числа днів у місяці:

ДЕНЬ (КОНМЕСЯЦА (СЬОГОДНІ (); 0))

А ось у другій частині проводиться віднімання з цього показника сьогоднішнього числа:

ДЕНЬ (СЬОГОДНІ ())

Таким чином, при виконанні даного розрахунку формула обчислення кількості днів є складовою частиною більш складної формули.

Спосіб 4: альтернативна формула

Але, на жаль, у версій програми раніше Excel 2007 відсутня оператор КОНМЕСЯЦА. Як же бути тим користувачам, які застосовують старі версії додатка? Для них така можливість існує за допомогою іншої формули, яка більш масивна, ніж описувана вище. Подивимося, як розрахувати кількість днів у місяці за заданим календарного числа за допомогою цього варіанта.

  1. Виділяємо осередок для виведення результату і переходимо у вікно аргументів оператора ДЕНЬ вже звичним для нас способом. Встановлюємо курсор в єдине поле цього вікна і натискаємо по переверненому трикутнику зліва від рядка формул. Переходимо в розділ «Інші функції ...».
  2. У вікні майстри функцій у групі "Дата і час" виділяємо найменування «ДАТА» і тиснемо на кнопку «OK».
  3. Запускається віконце оператора ДАТА. Ця функція перетворює дату зі звичайного формату в числове значення, Яке і повинен буде потім обробити оператор ДЕНЬ.

    Вікно має три поля. У полі «День» можна відразу ввести число «1». Це буде незмінним дією для будь-якої ситуації. А ось двома іншими полями доведеться зайнятися грунтовно.

    Встановлюємо курсор в поле «Рік». Далі переходимо до вибору операторів через знайомий нам трикутник.

  4. Все в тій же категорії майстри функцій виділяємо найменування «РІК» і клацаємо по кнопці «OK».
  5. Запускається вікно аргументів оператора РІК. Він визначає рік по зазначеному числу. В єдиному полі вікна «Дата в числовому форматі» вказуємо посилання на клітинку, яка містить вихідну дату, для якої потрібно визначити кількість днів. Після цього не поспішаємо клацати по кнопці «OK», А натискаємо по найменуванню «ДАТА» в рядку формул.
  6. Потім ми знову повертається у вікно аргументів ДАТА. Встановлюємо курсор в поле «Місяць» і переходимо до вибору функцій.
  7. В Майстрі функцій клацаємо по найменуванню «МІСЯЦЬ» і тиснемо на кнопку «OK».
  8. Запускається вікно аргументів функції МІСЯЦЬ. Її завдання схожі з попереднім оператором, тільки вона виводить значення номера місяця. В єдине поле даного вікна встановлюємо ту ж саму посилання на вихідне число. Потім в рядку формул клацаємо по найменуванню «ДЕНЬ».
  9. Повертаємося у вікно аргументів ДЕНЬ. Тут нам належить зробити всього один невеликий штрих. В єдине поле вікна, в якому вже перебувають дані, додаємо в кінець формули вираз «-1» без лапок, а також ставимо «+1» після оператора МІСЯЦЬ. Після цього натискаємо на кнопку «OK».
  10. Як бачимо, в попередньо виділеної осередку відобразилося кількість днів у місяці, до якого належить вказане число. Загальна формула має такий вигляд:

    ДЕНЬ (ДАТА (РІК (D3); МІСЯЦЬ (D3) +1; 1) -1)

Секрет цієї формули простий. Ми за допомогою неї визначаємо дату першого дня наступного періоду, а потім забираємо від неї один день, отримуючи кількість днів в зазначеному місяці. Змінною величиною в цій формулі є посилання на осередок D3 в двох місцях. Якщо її замінити на адресу тієї комірки, в якій знаходиться дата в вашому конкретному випадку, то можна просто вбити цей вислів в будь-який елемент листа без допомоги майстри функцій.

Як бачимо, існує кілька варіантів дізнатися кількість днів у місяці в Excel. Яким саме з них скористатися, залежить від кінцевої мети користувача, а також від того, якою версією програми він користується.

Калькулятор дат призначений для обчислення кількості днів між датами, а також для знаходження дати шляхом додавання або віднімання певної кількості днів до відомої датою.

Додати дні до дати

Для того, щоб довідатися яке число буде через певну кількість днів, скористайтеся цією опцією. Введіть початкову дату і кількість днів, яке потрібно до неї додати. Для вирахування використовуйте значення з мінусом. У калькуляторі також є опція для додавання тільки робочих днів.

Обчислення кількості днів між датами

Цей метод розрахунку відповість на питання "скільки днів пройшло з дати". Введіть початкову дату і кінцеву дату і натисніть кнопку "розрахувати". Калькулятор покаже, скільки днів між введеними датами. Окремо калькулятор покаже кількість робочих днів.

За допомогою цієї опції можна обчислити скільки днів залишилося до певної події, наприклад до дня народження або свята. Для цього в поле початкової дати вкажіть сьогоднішнє число, а в поле кінцевої дати - дату події.

Святкові дні

Калькулятор може обчислювати, додавати і віднімати як календарні дні, так і робочі. офіційними неробочими святковими днями є:

  • 1,2,3,4,5,6,8 січня - новорічні канікули
  • 7 січня - православне Різдво
  • 23 лютого - День захисника Вітчизни
  • 8 березня - Міжнародний жіночий день
  • 1 травня - Свято Весни і Праці
  • 9 травня День Перемоги
  • 12 червня - День Росії
  • 4 листопада - День народної єдності

Якщо святковий день випав на суботу або неділю, його переносять на найближчий робочий день. Але іноді вихідні переносять зовсім в інше місце календаря. Наприклад, суботу та неділю, що випали на новорічні свята, можуть перенести на травень, щоб продовжити травневі свята.

Калькулятор при розрахунку днів враховує як офіційні святкові дати, так і всі перенесення.

Примітка: Даний пост є перекладом статті cmcenroe.me/2014/12/05/days-in-month-formula.html ( частина I), А також авторським до нього доповненням ( частина II). Не слід ставитися до матеріалу серйозно, а скоріше як до розминки для розуму, що вимагає не більше ніж шкільних знань арифметики і не має практичного застосування. Всім приємного читання!

частина I

вступ

Нещодавно, після чергової безсонної ночі, я розмірковував про методи запам'ятовування кількості днів у кожному місяці року. Для цього є лічилки, а також спосіб вважати на кісточках пальців, але ні те, ні інше мене не влаштувало. Я задумався, а чи не існує якоїсь математичної формули для вирішення такого завдання, і - не знайшовши при побіжному вивченні таку - кинув собі виклик її створити.

Формалізуючи Іншими словами, необхідно знайти функцію f, Таку, що значення f (x) для кожного місяця x, Представленого числом від 1 до 12, дорівнює кількості днів у цьому місяці. Таблиця значень аргументу і функції:

x 1 2 3 4 5 6 7 8 9 10 11 12
f (x) 31 28 31 30 31 30 31 31 30 31 30 31

Якщо у вас виникло бажання спробувати самому до прочитання мого рішення, то зараз саме час. Якщо ж ви віддаєте перевагу негайно побачити готову відповідь, то подивіться під спойлер.

відповідь


Нижче наведені мої кроки по знаходженню рішення.

математичний апарат

Спочатку побіжно освіжимо в пам'яті два життєво необхідних у вирішенні цього завдання оператора: цілочисельне ділення і залишок від ділення.

цілочисельне діленняце оператор, який застосовується в багатьох мовах програмування при розподілі двох цілих чисел і відкидає від приватного дробову частину. Я буду зображати його як. наприклад:

Залишок від ділення це оператор, що знаходить залишок від ділення. У багатьох мовах програмування застосовується символ % , Я ж буду використовувати конструкції виду, наприклад:

Зауважу, що залишок від ділення має рівний з розподілом пріоритет.

основи

Отже, застосуємо наш математичний апарат для отримання базової формули. У звичайному місяці 30 або 31 день, так що ми можемо використовувати для отримання черзі 1 або 0, а потім просто додати до цього числа константу:

Отримуємо таблицю, напівжирним виділені коректні значення:
x 1 2 3 4 5 6 7 8 9 10 11 12
f (x) 31 30 31 30 31 30 31 30 31 30 31 30

Непоганий початок! Вже є правильні значення для січня і для місяців з березня по липень включно. Лютий - особливий випадок, і з ним ми розберемося трохи пізніше. Після липня для решти місяців порядок отримання 0 і 1 має бути змінений на зворотний.
Для цього ми може додати до делимому 1:

x 1 2 3 4 5 6 7 8 9 10 11 12
f (x) 30 31 30 31 30 31 30 31 30 31 30 31

Тепер правильні значення з серпня по грудень, але, як і передбачалося, значення для інших місяців невірні. Давайте подивимося як ми можемо об'єднати ці формули.

накладення маски

Для цього необхідна кусочно-задана функція, але - так як мені це здалося нудним - я задумався про інший шлях вирішення, що використовує одну частину функції на одному інтервалі, іншу - на іншому.
Вважаю, що найпростіше буде знайти вираз, що дорівнює 1 в одній області застосування і 0 - в решті. Метод, в якому множачи аргумент на вираз ми виключаємо його з формули поза області його застосування, я назвав «накладенням маски», тому така поведінка подібно якоїсь бітової масці.
Для застосування цього методу в останній частині нашої функції необхідно знайти вираз, що дорівнює 1 при, і - так як значення аргументу завжди менше 16 - для цього прекрасно підходить цілочисельне ділення на 8.
x 1 2 3 4 5 6 7 8 9 10 11 12
x ⁄ 8 ⌋ 0 0 0 0 0 0 0 1 1 1 1 1

Тепер за допомогою цієї маски, використовуючи в подільному вираз замість 1, ми можемо замінити порядок отримання 0 і 1 формулою на зворотний:

x 1 2 3 4 5 6 7 8 9 10 11 12
f (x) 31 30 31 30 31 30 31 31 30 31 30 31

Еврика! Все правильно, крім лютого. Сюрприз-сюрприз.

Лютий

У будь-якому місяці 30 або 31 день, крім лютого з його 28 (високосний рік виходить за рамки цього завдання). На поточний момент по нашій формулі в ньому 30 днів, тому непогано б відняти вираз, що дорівнює 2 при.
Найкраще що мені вдалося придумати це, що накладає маску на всі місяці після лютого:
x 1 2 3 4 5 6 7 8 9 10 11 12
2 mod x 0 0 2 2 2 2 2 2 2 2 2 2

Змінивши базову константу на 28 з додаванням 2 до решти місяців отримаємо формулу:

x 1 2 3 4 5 6 7 8 9 10 11 12
f (x) 29 28 31 30 31 30 31 31 30 31 30 31

На жаль, січень тепер коротше на 2 дня. Але, на щастя, отримати вираз, яке буде застосовуватися тільки для першого місяця дуже легко: це округлене вниз зворотне до число. Помноживши його на 2 отримуємо остаточну формулу:

x 1 2 3 4 5 6 7 8 9 10 11 12
f (x) 31 28 31 30 31 30 31 31 30 31 30 31

Післямова

Ось вона - формула для отримання кількості днів у будь-якому місяці року, що використовує найпростішу арифметику. Наступного разу коли ви будете згадувати скільки ж днів у вересні, просто виконайте за допомогою цієї однорядковою функції на JavaScript:

Function f (x) (return 28 + (x + Math.floor (x / 8))% 2 + 2% x + 2 * Math.floor (1 / x);)

частина II

вступ

У першій частині була отримана коротка і навіть трохи витончена формула, основними перевагами якої є простота математичного апарату, відсутність розгалужень і умовних виразів, лаконічність. До недоліків - крім того, що ви не будете застосовувати її в вашому проекті - можна віднести відсутність перевірки на віскокосний і не високосний рік.
Тому я поставив перед собою завдання створити функцію f, Таку, що значення f (x, y) для кожного місяця x, Представленого числом від 1 до 12 і роки y, Більшого 0, дорівнює кількості днів у місяці x в році y.
Для нетерплячих під спойлером знаходиться готову відповідь, інших же прошу слідувати за мною.

відповідь

Залишок від ділення: mod і ⌊⌋

Для візуальної наочності домовимося, що в деяких формулах оператор ділення із залишком замінений нижніми дужками, там де це здалося мені необхідним:

Високосний рік

У високосний рік вводиться додатковий день календаря: 29 лютого. Як відомо, високосним є рік, кратний 4 і не кратний 100, або кратний 400. Запишемо тотожне цього висловлювання вираз:

Для приведення цього виразу в алгебраїчне, необхідно застосувати до результату виразу ін'єкцію виду:

Що дозволить отримати 1 при діленні без залишку і 0 при діленні з залишком, щоб використовувати її у формулі визначення кількості днів у місяці.

В якості опції g " можна використовувати 1 мінус залишок від ділення для:

x 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
g "(x) Infinity 1 0 0 0 0 0 0 0 0 0 0 0 0 0

Легко помітити, що збільшивши ділене і дільник на 1 ми отримаємо правильну формулу при:
x 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
g "(x) 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0

Таким чином вираз запишемо як:


А вираз запишемо як:

Застосовуючи цей підхід отримаємо таку функцію g (y), Значенням якої буде 1, якщо рік високосний, чи 0 в зворотному випадку:

y 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000
g (y) 0 0 1 0 0 0 1 0 0 0 1
y 2000 2100 2200 2300 2400 2500 2600 2700 2800 2900 3000
g (y) 1 0 0 0 1 0 0 0 1 0 0

Напівжирним виділені високосні роки.

Нагадую, що в рамках прийнятої домовленості оператор отримання залишку від ділення може бути зображений як mod, так і ⌊⌋.

накладення маски

У формулі частина є поправкою, яка додає 2 дня до січня. Якщо прибрати множник 2 і в чисельнику замінити 1 на 2, тоді ця формула буде додавати 2 дні до січня і 1 день до лютого, що дає нам ключ до додаванню дня у високосному році. Для наочності використовуємо у формулі проміжне значення g (y) і в якості y використовуємо 2000 (високосний) і 2001 (невисокосному) роки:

x 1 2 3 4 5 6 7 8 9 10 11 12
f (x, 2000) 31 29 31 30 31 30 31 31 30 31 30 31
f (x, 2001) 30 28 31 30 31 30 31 31 30 31 30 30

Значення для всіх місяців, крім січня не високосного року вірні.

Для виправлення цього прикрого непорозуміння додамо до січня 1 день вже відомої нам формулою:


або:

x 1 2 3 4 5 6 7 8 9 10 11 12
f (x, 2000) 31 29 31 30 31 30 31 31 30 31 30 31
f (x, 2001) 31 28 31 30 31 30 31 31 30 31 30 30

висновок

В результаті отримана вже значно більш громіздка, але більш універсальна формула, яку також можна використовувати для отримання кількості днів у місяці певного року:

Function f (x, y) (return 28 + ((x + Math.floor (x / 8))% 2) + 2% x + Math.floor ((1 + (1 - (y% 4 + 2)% (y% 4 + 1)) * ((y% 100 + 2)% (y% 100 + 1)) + (1 - (y% 400 + 2)% (y% 400 + 1))) / x) + Math.floor (1 / x) - Math.floor (((1 - (y% 4 + 2)% (y% 4 + 1)) * ((y% 100 + 2)% (y% 100 + 1 )) + (1 - (y% 400 + 2)% (y% 400 + 1))) / x);)
Приклад на C # ideone.com/fANutz.

1 . Я не вмію користуватися подібною мнемонікою, тому підглянув табличку в інтернеті.
2 . «Основи», або «Правило З Багатьма Винятками», як і більшість правил.
3 . Спочатку в римському календарі лютого був останнім місяцем року, тому є логіка в тому, що він коротше всіх інших. Також є логіка в додаванні або видаленні дня саме в кінці року, тому його довжина є змінною.

Upd. 1:
Альтернативний переклад першої частини в



Сподобалася стаття? поділіться їй