Определение дня недели с помощью конгруэнтности Целлера

Я попытался написать код для определения дня недели для заданной даты, используя Конгруэнцию Целлера. но я не получаю правильный вывод. Что не так с моим кодом?

#include <stdio.h>
#include <math.h>
int main()
{
  int h,q,m,k,j,day,month,year;
  printf("Enter the date (dd/mm/yyyy)\n");
  scanf("%i/%i/%i",&day,&month,&year);
  if(month == 1)
  {
    month = 13;
    year--;
  }
  if (month == 2)
  {
    month = 14;
    year--;
  }
  q = day;
  m = month;
  k = year % 100;
  j = year / 100;
  h = q + floor(13/5*(m+1)) + k + floor(k/4) +  floor(j/4) + 5 * j;
  h = h % 7;
  switch(h)
  {
    case 0 : printf("Saturday.\n"); break;
    case 1 : printf("Sunday.\n"); break;
    case 2 : printf("Monday. \n"); break;
    case 3 : printf("Tuesday. \n"); break;
    case 4 : printf("Wednesday. \n"); break;
    case 5 : printf("Thurday. \n"); break;
    case 6 : printf("Friday. \n"); break;
  }
  return 0;
}

person Shail    schedule 28.02.2013    source источник
comment
Из статьи в Википедии следует, что вы не должны уменьшать год в используемой вами версии формулы.   -  person Yaniv    schedule 28.02.2013
comment
@Yaniv Я пытался удалить декременты, но результат был неправильным.   -  person Shail    schedule 28.02.2013


Ответы (2)


Вот рабочая версия:

#include <stdio.h>
#include <math.h>
int main()
{
  int h,q,m,k,j,day,month,year;
  printf("Enter the date (dd/mm/yyyy)\n");
  scanf("%i/%i/%i",&day,&month,&year);
  if(month == 1)
  {
    month = 13;
    year--;
  }
  if (month == 2)
  {
    month = 14;
    year--;
  }
  q = day;
  m = month;
  k = year % 100;
  j = year / 100;
  h = q + 13*(m+1)/5 + k + k/4 + j/4 + 5*j;
  h = h % 7;
  switch(h)
  {
    case 0 : printf("Saturday.\n"); break;
    case 1 : printf("Sunday.\n"); break;
    case 2 : printf("Monday. \n"); break;
    case 3 : printf("Tuesday. \n"); break;
    case 4 : printf("Wednesday. \n"); break;
    case 5 : printf("Thurday. \n"); break;
    case 6 : printf("Friday. \n"); break;
  }
  return 0;
}

Прямая демонстрация.

Ключ в вашей формуле h: 13/5*(m+1). Здесь используется целочисленное деление, которое сначала вычисляет 13/5, поэтому результат эквивалентен 2*(m+1). Поменяйте местами 5 и (m+1), и результат будет правильным.

Кстати, вам нужно уменьшить год, если январь / февраль, как объясняется в статье вики.

person congusbongus    schedule 28.02.2013
comment
Спасибо! Итак, поскольку это целочисленное деление, нет необходимости в этаже, верно? - person Shail; 28.02.2013
comment
@Шаил да, пол не нужен - person congusbongus; 28.02.2013

Почему вы включаете «h = год% 100» и «j = год / 100»?????

#include <stdio.h>
#include <math.h>
int main()
{
  int h,q,m,k,j,day,month,year;
  printf("Enter the date (dd/mm/yyyy)\n");
  scanf("%i/%i/%i",&day,&month,&year);
  if(month == 1)
  {
    month = 13;
    year--;
  }
  if (month == 2)
  {
    month = 14;
    year--;
  }
  q = day;
  m = month;
  k = year % 100;
  j = year / 100;
  h = q + 13*(m+1)/5 + k + k/4 + j/4 + 5*j;
  h = h % 7;
  switch(h)
  {
    case 0 : printf("Saturday.\n"); break;
    case 1 : printf("Sunday.\n"); break;
    case 2 : printf("Monday. \n"); break;
    case 3 : printf("Tuesday. \n"); break;
    case 4 : printf("Wednesday. \n"); break;
    case 5 : printf("Thurday. \n"); break;
    case 6 : printf("Friday. \n"); break;
  }
  return 0;
}
person Tyler Gates    schedule 13.12.2016
comment
Вы включаете k = год % 100 и j = год / 100, потому что k определяется как две последние цифры года, а j определяется как первые две. Итак, на 2019 год k равно 19, а j равно 20. - person MiguelMunoz; 19.10.2019