![有人能解释一下 Taco Hoekwater 计算周数的算法吗?](https://linux22.com/image/305256/%E6%9C%89%E4%BA%BA%E8%83%BD%E8%A7%A3%E9%87%8A%E4%B8%80%E4%B8%8B%20Taco%20Hoekwater%20%E8%AE%A1%E7%AE%97%E5%91%A8%E6%95%B0%E7%9A%84%E7%AE%97%E6%B3%95%E5%90%97%EF%BC%9F.png)
Taco Hoekwater 在 2006 年编写了一个算法,计算周数。该算法大部分情况下都能正确计算周数,但显然遗漏了 2015 年的前 4 天。如果不解释该算法,就无法理解哪里出了问题。
有人能解释一下这个算法到底是怎么回事吗?
\documentclass{article}
%% calendarweek.tex
%% 2006 (C) Taco Hoekwater, public domain
%% Watch out: Dec 29 can be week 1 of the next year; and Jan 3 can be
%% week 53 of the previous year.
\def\Expr#1{\the\numexpr #1\relax}
\def\Modulonumber#1#2{\Expr{#2-((((#2+(#1/2))/#1)-1)*#1)}}
\def\Divisionnumber#1#2{\Expr{(2*#2-#1)/(2*#1)}}
\def\Mod#1#2{\Modulonumber{\Expr{#2}}{\Expr{#1}}}
\def\Div#1#2{\Divisionnumber{\Expr{#2}}{\Expr{#1}}}
\def\Jday#1#2#3%
{\Expr{#1+\Div{((153*(\Expr{#2+(12*(\Div{14-#2}{12}))-3}))+2)}
{5}+365*(\Expr{#3+4800-(\Div{14-#2}{12})})+
(\Div{\Expr{#3+4800-(\Div{14-#2}{12})}}{4})-
(\Div{\Expr{#3+4800-(\Div{14-#2}{12})}}{100})+
(\Div{\Expr{#3+4800-(\Div{14-#2}{12})}}{400})-32045 }}
\def\cwhlp#1#2#3%
{\Expr{\Mod {\Mod {\Mod {\Expr
{\Jday{#1}{#2}{#3}+31741-\Mod{\Jday{#1}{#2}{#3}}{7}}}%
{146097}}{36524}}{1461}}}
\def\calendarweek#1#2#3%
{\Expr{\Expr{\Div{\Expr{\Mod{\cwhlp{#1}{#2}{#3}-
\Expr{\Div{\cwhlp{#1}{#2}{#3}}{1460}}}{365}+
\Expr{\Div{\cwhlp{#1}{#2}{#3}}{1460}}}}{7} +1}}}
\begin{document}
Week 1-1-2015 = \calendarweek{01}{01}{2015} %% returns 0
Week 2-1-2015 = \calendarweek{02}{01}{2015} %% returns 0
Week 3-1-2015 = \calendarweek{03}{01}{2015} %% returns 0
Week 4-1-2015 = \calendarweek{04}{01}{2015} %% returns 0
Week 5-1-2015 = \calendarweek{05}{01}{2015} %% returns 2
\end{document}
答案1
在ISO,正如评论中提到的,一周是第一周还是第五十三周取决于它的星期四。或者说,一周在新年还是旧年有更多的天数。
为了以数学方式计算这一点,可以考虑Round()
满足
Round(n+0.4)=n
, 和Round(n+0.6)=n+1
。
然后进行一些计算,如b := Round(a/7)
和c := b%53+1
。(现在我想要 MathJax...)
问题是,在您的.tex
文件中,该函数(a,b) |--> Round(b/a)
的实现方式为
\def\Divisionnumber#1#2{\Expr{(2*#2-#1)/(2*#1)}}
这MyRound[(2b-a)/2a] = MyRound[b/a-1/2]
满足:
\Divisionnumber{7}{14}= 2
\Divisionnumber{7}{ 7}= 1
\Divisionnumber{7}{ 0}=-1
\Divisionnumber{7}{-7}=-2
这给出了错误的数字。
为了解决这个问题,因为在这种情况下分子总是非负的,我建议:
\def\Divisionnumber#1#2{\Expr{(2*#2+#1)/(2*#1)-1}}
因此[(2b+a)/2a]-1 = MyRound[b/a+1/2]-1
满足:
\Divisionnumber{7}{14}= 2
\Divisionnumber{7}{ 7}= 1
\Divisionnumber{7}{ 0}= 0
\Divisionnumber{7}{-7}=-2
一些测试代码...
\documentclass{article}
\def\Expr#1{\the\numexpr #1\relax}
\def\Modulonumber#1#2{\Expr{#2-((((#2+(#1/2))/#1)-1)*#1)}}
\def\Divisionnumber#1#2{\Expr{(2*#2-#1)/(2*#1)}}
\def\Mod#1#2{\Modulonumber{\Expr{#2}}{\Expr{#1}}}
\def\Div#1#2{\Divisionnumber{\Expr{#2}}{\Expr{#1}}}
\def\Jday#1#2#3%
{\Expr{#1+\Div{((153*(\Expr{#2+(12*(\Div{14-#2}{12}))-3}))+2)}
{5}+365*(\Expr{#3+4800-(\Div{14-#2}{12})})+
(\Div{\Expr{#3+4800-(\Div{14-#2}{12})}}{4})-
(\Div{\Expr{#3+4800-(\Div{14-#2}{12})}}{100})+
(\Div{\Expr{#3+4800-(\Div{14-#2}{12})}}{400})-32045 }}
\def\cwhlp#1#2#3% H = (\J+31741-\J%7)%146097%36524%1461
{\Expr{\Mod {\Mod {\Mod {\Expr
{\Jday{#1}{#2}{#3}+31741-\Mod{\Jday{#1}{#2}{#3}}{7}}}%
{146097}}{36524}}{1461}}}
\def\calendarweek#1#2#3% W = [(H-H/1460)%365+H/1460]/7+1
{\Expr{\Expr{\Div{\Expr{\Mod{\cwhlp{#1}{#2}{#3}-
\Expr{\Div{\cwhlp{#1}{#2}{#3}}{1460}}}{365}+
\Expr{\Div{\cwhlp{#1}{#2}{#3}}{1460}}}}{7} +1}}}
\def\temp#1#2#3{
\def\a{\Expr{\Div{\cwhlp{#1}{#2}{#3}}{1460}}} % a = H/1460
\def\b{\Expr{\cwhlp{#1}{#2}{#3}-\a}} % b = H-a
\def\c{\Expr{\Mod{\b}{365}}} % c = b%365
\def\d{\Expr{\c+\a}} % d = c+a
\def\e{\Expr{\Div{\d}{7}}} % e = d/7
\def\f{\Expr{\e+1}} % f = e+1
\a\ \b\ \c\ \d\ \e\ \f
}
\usepackage{pgfkeys,pgfcalendar}%\usepackage{tikz}\usetikzlibrary{calendar}
\newcount\jcount
\newcount\wcount
\def\pgfjday#1#2#3{%
\pgfcalendardatetojulian{#3-#2-#1}{\jcount}%
\the\jcount
}
\begin{document}
\begin{tabular}{lllllllll}
2015-1-1&\pgfjday11{2015}&\Jday11{2015}&\cwhlp11{2015}&\temp11{2015}&\calendarweek11{2015} \\
2015-1-2&\pgfjday21{2015}&\Jday21{2015}&\cwhlp21{2015}&\temp21{2015}&\calendarweek21{2015} \\
2015-1-3&\pgfjday31{2015}&\Jday31{2015}&\cwhlp31{2015}&\temp31{2015}&\calendarweek31{2015} \\
2015-1-4&\pgfjday41{2015}&\Jday41{2015}&\cwhlp41{2015}&\temp41{2015}&\calendarweek41{2015} \\
2015-1-5&\pgfjday51{2015}&\Jday51{2015}&\cwhlp51{2015}&\temp51{2015}&\calendarweek51{2015} \\
\end{tabular}
\par\bigskip
\underline{\Divisionnumber{7}{14}}
\Divisionnumber{7}{13}
\Divisionnumber{7}{12}
\Divisionnumber{7}{11}
\Divisionnumber{7}{10}
\Divisionnumber{7}{ 9}
\Divisionnumber{7}{ 8}
\underline{\Divisionnumber{7}{ 7}}
\Divisionnumber{7}{ 6}
\Divisionnumber{7}{ 5}
\Divisionnumber{7}{ 4}
\Divisionnumber{7}{ 3}
\Divisionnumber{7}{ 2}
\Divisionnumber{7}{ 1}
\underline{\Divisionnumber{7}{ 0}}
\Divisionnumber{7}{-1}
\Divisionnumber{7}{-2}
\Divisionnumber{7}{-3}
\Divisionnumber{7}{-4}
\Divisionnumber{7}{-5}
\Divisionnumber{7}{-6}
\underline{\Divisionnumber{7}{-7}}
\bigskip % % % % % % % % % % % % % % %
\def\Divisionnumber#1#2{\Expr{(2*#2+#1)/(2*#1)-1}}
\begin{tabular}{lllllllll}
2015-1-1&\pgfjday11{2015}&\Jday11{2015}&\cwhlp11{2015}&\temp11{2015}&\calendarweek11{2015} \\
2015-1-2&\pgfjday21{2015}&\Jday21{2015}&\cwhlp21{2015}&\temp21{2015}&\calendarweek21{2015} \\
2015-1-3&\pgfjday31{2015}&\Jday31{2015}&\cwhlp31{2015}&\temp31{2015}&\calendarweek31{2015} \\
2015-1-4&\pgfjday41{2015}&\Jday41{2015}&\cwhlp41{2015}&\temp41{2015}&\calendarweek41{2015} \\
2015-1-5&\pgfjday51{2015}&\Jday51{2015}&\cwhlp51{2015}&\temp51{2015}&\calendarweek51{2015} \\
\end{tabular}
\par\bigskip
\underline{\Divisionnumber{7}{14}}
\Divisionnumber{7}{13}
\Divisionnumber{7}{12}
\Divisionnumber{7}{11}
\Divisionnumber{7}{10}
\Divisionnumber{7}{ 9}
\Divisionnumber{7}{ 8}
\underline{\Divisionnumber{7}{ 7}}
\Divisionnumber{7}{ 6}
\Divisionnumber{7}{ 5}
\Divisionnumber{7}{ 4}
\Divisionnumber{7}{ 3}
\Divisionnumber{7}{ 2}
\Divisionnumber{7}{ 1}
\underline{\Divisionnumber{7}{ 0}}
\Divisionnumber{7}{-1}
\Divisionnumber{7}{-2}
\Divisionnumber{7}{-3}
\Divisionnumber{7}{-4}
\Divisionnumber{7}{-5}
\Divisionnumber{7}{-6}
\underline{\Divisionnumber{7}{-7}}
\end{document}