<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[Science and software]]></title><description><![CDATA[A newsletter for scientists and engineers about bringing your models to the web. Up to five short emails per week.]]></description><link>https://antonischristofides.substack.com</link><image><url>https://substackcdn.com/image/fetch/$s_!iQTT!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F695cda63-0317-4f9f-8fd1-8a33c628e620_256x256.png</url><title>Science and software</title><link>https://antonischristofides.substack.com</link></image><generator>Substack</generator><lastBuildDate>Mon, 20 Apr 2026 17:06:09 GMT</lastBuildDate><atom:link href="https://antonischristofides.substack.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Antonis Christofides]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[antonischristofides@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[antonischristofides@substack.com]]></itunes:email><itunes:name><![CDATA[Antonis Christofides]]></itunes:name></itunes:owner><itunes:author><![CDATA[Antonis Christofides]]></itunes:author><googleplay:owner><![CDATA[antonischristofides@substack.com]]></googleplay:owner><googleplay:email><![CDATA[antonischristofides@substack.com]]></googleplay:email><googleplay:author><![CDATA[Antonis Christofides]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[How to avoid JavaScript]]></title><description><![CDATA[Despite the JavaScript revolution, people still resist it]]></description><link>https://antonischristofides.substack.com/p/how-to-avoid-javascript</link><guid isPermaLink="false">https://antonischristofides.substack.com/p/how-to-avoid-javascript</guid><dc:creator><![CDATA[Antonis Christofides]]></dc:creator><pubDate>Thu, 08 Jul 2021 08:19:37 GMT</pubDate><enclosure url="https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/3280f3ce-2d5a-476e-b488-0b33122ed2e6_5627x3751.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A month ago I attended Django Conference Europe. I was surprised to see how many talks dealt with the issue of how to avoid JavaScript. One of these talks, for example, had the title &#8220;How to create a full-stack, reactive website in Django with absolutely no JavaScript&#8221;. Solutions vary from small JavaScript libraries like HTMX, which are clever and help in simple cases (and might be all you need), to the impressive Anvil platform, in which you program the full stack in Python, and it compiles some of the Python to JavaScript for the front-end part.</p><p>I couldn&#8217;t help but ask myself &#8220;why don&#8217;t these people just learn JavaScript?&#8221; The answer is easy. I&#8217;ve been slowly learning JavaScript for years and I&#8217;m still not there&#8212;because I don&#8217;t have much time to spend. And the other question is &#8220;why don&#8217;t we hire a JavaScript person to write the JavaScript part?&#8221; There are many possible answers to this. One is that we like to be able to do everything ourselves, something valuable in small and hobby projects. Another possibility is that good JavaScript programmers are hard to find. And going from a team of one to a team of two people is no small step.</p>]]></content:encoded></item><item><title><![CDATA[Stunning the non-JavaScript web developers]]></title><description><![CDATA[What were the Django people doing while JavaScript was becoming popular?]]></description><link>https://antonischristofides.substack.com/p/stunning-the-non-javascript-web-developers</link><guid isPermaLink="false">https://antonischristofides.substack.com/p/stunning-the-non-javascript-web-developers</guid><dc:creator><![CDATA[Antonis Christofides]]></dc:creator><pubDate>Wed, 07 Jul 2021 08:14:25 GMT</pubDate><enclosure url="https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/d62031bd-d84f-46b5-b795-2efa849988f1_559x363.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you&#8217;ve been following my last six posts, you know that a revolution around JavaScript started in 2008 and became more like an explosion from 2015 onwards. What were the non-JavaScript web developers doing in the meantime?</p><p>I can tell you about myself. For about 10 years, I ignored and resisted all that.</p><p>Yes, like everyone, I&#8217;m always busy, and there are tons of things to learn anyway. I had wanted to learn a little JavaScript since 2000 but I had never got to it.</p><p>But I think it may have been more to it than that. JavaScript was a bad language. I didn&#8217;t want to program in a bad language. I was using serious stuff like Python and Django. I was too self-important to engage in inferior tools.</p><p>It&#8217;s not just conceit. Very often there&#8217;s a new fashion that explodes, only to die off a bit later. Like XML, for example. In the last 30 years I avoided investing in technologies that didn&#8217;t seem right to me, and usually I was proven right. JavaScript was the exception.</p><p>I think that many Python people acted the same as I.</p><p>A month ago I participated in the Django Conference Europe, and I was surprised at how people are approaching the JavaScript problem. This conference was the incentive for me to write this series. What I saw at the conference is the subject for next time.</p>]]></content:encoded></item><item><title><![CDATA[How JavaScript became popular—recap]]></title><description><![CDATA[The JavaScript explosion was initiated by a series of events from 2008 to 2015]]></description><link>https://antonischristofides.substack.com/p/how-javascript-became-popularrecap</link><guid isPermaLink="false">https://antonischristofides.substack.com/p/how-javascript-became-popularrecap</guid><dc:creator><![CDATA[Antonis Christofides]]></dc:creator><pubDate>Tue, 06 Jul 2021 15:20:51 GMT</pubDate><enclosure url="https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/b29ca054-e2b2-45ba-a9bf-39a98f4433a2_1476x1080.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>To round up this story of how JavaScript was transformed from a bad, hated and little-used language to an immensely popular, powerful and somewhat decent language, here are some of the most important events:</p><ul><li><p>2008: Google releases Chrome, which includes the incredibly fast V8 JavaScript engine</p></li><li><p>2009: Ryan Dahl creates Node.js, a command-line JavaScript engine based on V8</p></li><li><p>2013: Facebook creates React, a JavaScript framework for building UIs</p></li><li><p>2014: Sebastian McKenzie creates Babel, a compiler that transforms from one version of JavaScript to another</p></li><li><p>2015: ECMA publishes the final version of ES6 aka ES2015, a much better version of JavaScript</p></li></ul><p>This concise list is not very informative, so if you are interested but haven&#8217;t read my previous posts it&#8217;s better to do so, starting from &#8220;<a href="https://antonischristofides.substack.com/p/how-javascript-became-popularpart">How JavaScript became popular&#8212;part 1</a>&#8221;.</p><p>What did the Python people and other non-JavaScript people do during this revolution? This is a story for next time.</p>]]></content:encoded></item><item><title><![CDATA[How JavaScript became popular—part 5]]></title><description><![CDATA[The frameworks changed the way web applications work]]></description><link>https://antonischristofides.substack.com/p/how-javascript-became-popularpart-dc9</link><guid isPermaLink="false">https://antonischristofides.substack.com/p/how-javascript-became-popularpart-dc9</guid><dc:creator><![CDATA[Antonis Christofides]]></dc:creator><pubDate>Mon, 05 Jul 2021 08:19:50 GMT</pubDate><enclosure url="https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/4b5f8716-1a0d-430c-8acd-f87374fed597_1420x695.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In traditional web sites and applications, the browser connects to the server (e.g. &#8220;antonischristofides.substack.com&#8221;), makes a request (e.g. &#8220;Please give me the page with path &#8216;/p/how-javascript-became-popularpart-e65&#8217;&#8221;), and the server provides a response in HTML; e.g. something like</p><pre><code>&lt;h1&gt;How JavaScript became popular&#8212;part 5&lt;/h1&gt;

&lt;p class="subtitle"&gt;The frameworks changed the way web applications work&lt;/p&gt;

...</code></pre><p>If the user clicks on a link, the browser makes a new request and receives another response in HTML, i.e. another web page, which replaces the page that was previously visible.</p><p>Modern web applications written with the so-called &#8220;JavaScript frameworks&#8221; work differently. A JavaScript program that runs on the browser makes a request and receives a structured response like this:</p><pre><code>{
    title: "How JavaScript became popular&#8212;part 5",
    subtitle: "The frameworks changed the way web applications work",
    ...
}</code></pre><p>The JavaScript program reads the data from the response and creates the HTML itself, which it then shows on the browser.</p><p>The result is web applications that are much faster and more pleasant to use for the user. You can feel the difference when you use different kinds of web applications.</p><p>There are three JavaScript UI frameworks, i.e. libraries, that help programmers write such modern applications: React (2013), Vue.js (2014), and Angular (2016). These were the last thing that contributed to JavaScript&#8217;s exploding popularity.</p><p>Related:</p><ul><li><p><a href="https://antonischristofides.substack.com/p/how-javascript-became-popularpart-e65">How JavaScript became popular&#8212;part 4</a></p></li></ul>]]></content:encoded></item><item><title><![CDATA[How JavaScript became popular—part 4]]></title><description><![CDATA[JavaScript was a bad language but Babel helped work around the problem]]></description><link>https://antonischristofides.substack.com/p/how-javascript-became-popularpart-e65</link><guid isPermaLink="false">https://antonischristofides.substack.com/p/how-javascript-became-popularpart-e65</guid><dc:creator><![CDATA[Antonis Christofides]]></dc:creator><pubDate>Wed, 30 Jun 2021 09:31:25 GMT</pubDate><enclosure url="https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/e290a195-d706-432b-8ee1-ec8cae4e0548_667x879.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>JavaScript was an incredibly bad language. I don&#8217;t need to elaborate on this, since tons have been written; just search the web for &#8220;how bad is JavaScript&#8221;. Douglas Crockford&#8217;s classic book, &#8220;JavaScript: The Good Parts&#8221;, advocates using a subset of JavaScript (the good parts, that is), and has two appendixes: &#8220;The Awful Parts&#8221; and &#8220;The Bad Parts&#8221;.</p><p>Many programmers would rather not have anything to do with such an abomination, but JavaScript was the language of the browsers, and they couldn&#8217;t avoid it. One solution was to create new programming languages which compiled to JavaScript, such as CoffeeScript (2009) and Microsoft&#8217;s TypeScript (2012), which today is very widely used. In 2014 a teenager created Babel, a library that could compile the next version of JavaScript to the previous one (today it can also compile TypeScript and many other JavaScript extensions). This was important because the 2015 version of JavaScript had several new features that made it somewhat bearable, but it would be years before all browsers supported these features.</p><p>We are nearing the end of this story, and to complete it we need to talk about the JavaScript UI frameworks, a story for next time.</p><p>Related:</p><ul><li><p><a href="https://antonischristofides.substack.com/p/how-javascript-became-popularpart-468">How JavaScript became popular&#8212;part 3</a></p></li></ul>]]></content:encoded></item><item><title><![CDATA[How JavaScript became popular—part 3]]></title><description><![CDATA[Running the same language on the server and on the browser was quite appealing]]></description><link>https://antonischristofides.substack.com/p/how-javascript-became-popularpart-468</link><guid isPermaLink="false">https://antonischristofides.substack.com/p/how-javascript-became-popularpart-468</guid><dc:creator><![CDATA[Antonis Christofides]]></dc:creator><pubDate>Fri, 25 Jun 2021 07:58:29 GMT</pubDate><enclosure url="https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/865ac520-5bcd-4dff-ac97-79f0568c3c8e_3984x2656.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><a href="https://antonischristofides.substack.com/p/how-javascript-became-popularpart-4e1">In 2009,  &#8220;Node.js&#8221; was released, a free command-line JavaScript environment that ran without a browser.</a> Until that time, the server part of web applications was written in Python or Ruby or Java or PHP or in some other language, but normally not on JavaScript, since JavaScript was for the browser only. But Node.js made it possible to write the server part of the web application in JavaScript. There were many reasons this was very appealing:</p><ul><li><p>You only needed one language, JavaScript, which could run both on the server and on the browser.</p></li><li><p>Some code could be shared between browser and server. Otherwise we often write the same piece of functionality in e.g. Python, so that the server can run it, and in JavaScript, so that the browser can run it.</p></li><li><p>Node.js was <a href="https://antonischristofides.substack.com/p/how-javascript-became-popularpart">very fast</a>.</p></li><li><p>JavaScript is an asynchronous language by design. I&#8217;m not going into detail about what this means, but it&#8217;s a good thing for servers. Python only got standard asynchronous features in 2014, whereas JavaScript was asynchronous in the core from day one in 1995.</p></li></ul><p>It&#8217;s therefore no surprise that a year and a half after the first release of Node.js, Express.js, a web application framework for the server, was released.</p><p>There was a problem though. JavaScript sucked. It had some good parts, but it was a bad language. But this is a story for next time.</p>]]></content:encoded></item><item><title><![CDATA[How JavaScript became popular—part 2]]></title><description><![CDATA[In 2009 you no longer needed a browser to run JavaScript.]]></description><link>https://antonischristofides.substack.com/p/how-javascript-became-popularpart-4e1</link><guid isPermaLink="false">https://antonischristofides.substack.com/p/how-javascript-became-popularpart-4e1</guid><dc:creator><![CDATA[Antonis Christofides]]></dc:creator><pubDate>Fri, 18 Jun 2021 10:32:53 GMT</pubDate><enclosure url="https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/c2285bf9-5aab-4e89-bff7-423b6915478f_6000x4000.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><a href="https://antonischristofides.substack.com/p/how-javascript-became-popularpart">In 2008, Google Chrome was released, with its blazing fast V8 JavaScript engine.</a> V8 was free software. A year later, a software engineer took V8 and used it to create &#8220;Node.js&#8221;, a command-line JavaScript environment that ran without a browser. Here is an example of me executing the &#8220;node&#8221; command on my computer and then entering a JavaScript statement that prints &#8220;hello world&#8221;:</p><pre><code>anthony@seska:~$ <strong>node</strong>
Welcome to Node.js v14.17.0.
Type ".help" for more information.
&gt; <strong>console.log("hello world")
</strong>hello world
undefined
&gt; </code></pre><p>This is very similar to doing the same thing in Python:</p><pre><code>anthony@seska:~$ <strong>python3
</strong>Python 3.8.7 (default, Dec 23 2020, 12:32:20) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
&gt;&gt;&gt; <strong>print("hello world")
</strong>hello world
&gt;&gt;&gt; </code></pre><p>Now JavaScript was a language you could run everywhere&#8212;not just in the browser.</p><p>It&#8217;s amazing how things took off from there. But this is a story for the next time.</p>]]></content:encoded></item><item><title><![CDATA[How JavaScript became popular—part 1]]></title><description><![CDATA[Google Chrome precipitated the JavaScript revolution]]></description><link>https://antonischristofides.substack.com/p/how-javascript-became-popularpart</link><guid isPermaLink="false">https://antonischristofides.substack.com/p/how-javascript-became-popularpart</guid><dc:creator><![CDATA[Antonis Christofides]]></dc:creator><pubDate>Thu, 17 Jun 2021 12:35:17 GMT</pubDate><enclosure url="https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/2b86a348-b9f3-48a4-a569-a24b74daf80c_4272x2848.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the beginning (1995), JavaScript was used only to add a little functionality&#8212;usually superficial&#8212;to web pages. Its usage gradually increased. If you are one of the older people, maybe you remember your jaw dropping around 2005, when you first saw Google Maps&#8212;the first popular application that used a technique known as AJAX. But the story of the modern JavaScript revolution starts three years later with the release of Google Chrome and its JavaScript engine.</p><p>The JavaScript engine is the part of the browser that executes JavaScript. I like the term &#8220;engine&#8221; because it avoids questions concerning the difference between interpreters and compilers. Every browser has a JavaScript engine: Firefox&#8217;s is called SpiderMonkey and Safari&#8217;s is Nitro. Chrome, Edge and Opera all use the same JavaScript engine, V8, originally released as part of Google Chrome in 2008.</p><p>What was notable about Google Chrome and V8 was that it was fast. It analyzed the program and compiled the parts that could be compiled, running them in native speed. It also used many other optimizations. Chrome&#8217;s competitors soon copied these features, and today all JavaScript engines are equally fast. A few months ago I made some tests and I was surprised to see that, in many cases, JavaScript is five times faster than Python (although still much slower than pure compiled languages such as C).</p><p>The next milestone was the creation of &#8220;Node.js&#8221; in 2009. But this is a story for next time.</p><p></p>]]></content:encoded></item><item><title><![CDATA[Why most software is substandard]]></title><description><![CDATA[Programmers are condemned by the nature of programming itself to make bad software]]></description><link>https://antonischristofides.substack.com/p/why-most-software-is-substandard</link><guid isPermaLink="false">https://antonischristofides.substack.com/p/why-most-software-is-substandard</guid><dc:creator><![CDATA[Antonis Christofides]]></dc:creator><pubDate>Wed, 02 Jun 2021 09:19:50 GMT</pubDate><enclosure url="https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/1f192f6c-b7c3-495b-a2df-c7a680774e34_1280x720.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I just watched <a href="https://www.youtube.com/watch?v=FG6DWXxccKA&amp;list=PLY_che_OEsX0C5IkZcqPlrbKvce178kFD&amp;index=2">a great presentation at a virtual conference</a>. The presenter, Daniele Procida, supported this thesis:</p><ul><li><p>Programming is intrinsically pleasurable.</p></li><li><p>Most software is substandard.</p></li><li><p>Most software is substandard because programming is intrinsically pleasurable.</p></li></ul><p>Technically we program in order to solve the user&#8217;s problem. However, we get absorbed by the pleasure programming gives us, and therefore we focus on our pleasure rather on someone else&#8217;s (the user&#8217;s) pain. At least that&#8217;s what Daniele says. The problem is worsened by the fact that bad software usually doesn&#8217;t result in serious damage&#8212;it usually causes irritation or inconvenience. Therefore, programmers have the luxury to not care much about the actual problem they&#8217;re supposed to be solving.</p><p>Many of these observations apply to science also. Scientists do science because it gives them pleasure. The outcome of bad science is rarely life threatening. Is this the reason science is often substandard? I have some doubts on that but it&#8217;s certainly thought-provoking.</p>]]></content:encoded></item><item><title><![CDATA[p = [(13 + 8 × century) / 25]]]></title><description><![CDATA[Some names should be better left meaningless]]></description><link>https://antonischristofides.substack.com/p/p-13-8-century-25</link><guid isPermaLink="false">https://antonischristofides.substack.com/p/p-13-8-century-25</guid><dc:creator><![CDATA[Antonis Christofides]]></dc:creator><pubDate>Tue, 01 Jun 2021 08:46:57 GMT</pubDate><enclosure url="https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/159180e1-80d6-4fd6-9ace-f4e608632d43_922x671.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>To round up this series about the date of Easter, I&#8217;d like to look at this part of Gauss&#8217;s algorithm, which I&#8217;ve rewritten with improved variable names:</p><p><em>metonic_year</em> = <em>year</em> mod 19<br><em>century</em> = [<em>year </em>/ 100]<br><em>quadricentennial</em> = [<em>century</em> / 4]<br><em>p</em> = [(13 + 8 &#215; <em>century</em>) / 25]<br><em>M</em> = (15 - <em>p</em> + <em>century</em> - <em>quadricentennial</em>) mod 30<br><em>ndays_equinox_to_full_moon </em>= ((30 - 11) &#215; <em>metonic_year</em> + <em>M</em>) mod 30</p><p>How can we improve the names for <em>p</em> and <em>M</em>? Things are becoming difficult here. <em>M</em> is a correction that applies to the century, and <em>p</em> is so hard that Gauss got it wrong. He initially thought it was [<em>century</em> / 3], which gave wrong Easter dates from the year 4200 onwards. Gauss found about the error soon and made several failed attempts at fixing it, until a student of his finally found the correct expression about 15 years after the original paper.</p><p>The second observation is the number 11 in the last expression. The original algorithm doesn&#8217;t say 30 - 11, it says 19. Good luck explaining to someone that this is not the length of the Metonic cycle. Initially I had <em>DIFF_BETWEEN_12_MOONS_AND_A_YEAR</em> in place of 11, but this made the expression too long. Besides, I&#8217;d need to also use constant names for 30 (presumably the length of the lunar cycle), 19 (the length of the Metonic cycle) and more. It would make it harder to read.</p><p>One problem I&#8217;d try to correct is that the result isn&#8217;t actually the days from equinox to full moon&#8212;it&#8217;s actually the days from the day after the equinox to the day after the full moon. I might try to keep the name <em>ndays_equinox_to_full_moon</em> and instead change the algorithm so that the name is accurate. In fact, trying to improve the name of a variable often leads to entirely refactoring the code.</p><p>If I wanted to write a paper on this I&#8217;d continue these improvements, but I think I&#8217;ve said enough and I&#8217;ll stop here.</p><p></p>]]></content:encoded></item><item><title><![CDATA[Gregorian calendar fun fact]]></title><description><![CDATA[Why was the calendar moved by ten days? Why not nine or eleven?]]></description><link>https://antonischristofides.substack.com/p/gregorian-calendar-fun-fact</link><guid isPermaLink="false">https://antonischristofides.substack.com/p/gregorian-calendar-fun-fact</guid><dc:creator><![CDATA[Antonis Christofides]]></dc:creator><pubDate>Fri, 28 May 2021 08:30:19 GMT</pubDate><enclosure url="https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/6ec64f57-56ba-4b33-8079-26d1d2495809_1600x1067.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The Julian calendar is slow by 0.75 days per century. Like fixing the time of a slow clock by moving its hands forward, in 1582 it was decided to fix the date of the slow calendar by moving it ten days forward.</p><p>Why ten days? Why not nine or eleven?</p><p>If you ask a search engine this question, you&#8217;ll find lots of texts repeating the information that they wanted to restore the calendar as it was in 325 A.D., the date of the First Council of Nicaea.</p><p>But the number of additional leap days in the Julian Calendar from 325 to 1582 is one for each of the years 500, 600, 700; 900, 1000, 1100; 1300, 1400 and 1500. A total of nine days. Or, another way to calculate it, (1582 - 325) / 100 * 0.75 = 9.4 days.</p><p>Why ten days?</p><p>To get the answer, we need to unearth <a href="https://en.wikipedia.org/wiki/Inter_gravissimas">the Pope&#8217;s 1582 decision</a>. There, it says that they have arranged &#8220;to restore the vernal equinox to its original place from which it has already receded by about ten days since the Council of Nicaea&#8221;. A little bit further below it becomes more specific, decreeing that the vernal equinox is to be restored to the place where it &#8220;was placed by the fathers of the Council of Nicaea at the twelfth day before the Kalends of April&#8221; (<a href="https://en.wikipedia.org/wiki/Roman_calendar#Months">this is 21 March</a>).</p><p>Conclusion: always look up the original reference.</p><p>Here&#8217;s a similar question: Was the 1582 decision right in that the Council of Nicaea had placed the equinox on 21 March? Again, we&#8217;d need to consult the original reference, but it seems that the relevant part of the Council proceedings has been lost.</p>]]></content:encoded></item><item><title><![CDATA[Can math be written better?]]></title><description><![CDATA[Ideas from programming could help make math more understandable]]></description><link>https://antonischristofides.substack.com/p/can-math-be-written-better</link><guid isPermaLink="false">https://antonischristofides.substack.com/p/can-math-be-written-better</guid><dc:creator><![CDATA[Antonis Christofides]]></dc:creator><pubDate>Thu, 27 May 2021 09:10:10 GMT</pubDate><enclosure url="https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/68dd36d3-50a7-49a0-a124-e6546dd493ce_5060x3358.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you take a look at <a href="https://github.com/aptiko/easter/blob/1ea95ca583370f1ae59e6a2b58490ad641e52a9b/easter.py">the program that implements the Gauss Easter algorithm</a>, you&#8217;ll see it&#8217;s much longer and much more readable (although it still needs improvements). Compare it to <a href="https://antonischristofides.substack.com/p/easter-algorithms">the original algorithm</a>:</p><p><em>a</em> = <em>year</em> mod 19<br><em>b</em> = <em>year</em> mod 4<br><em>c</em> = <em>year</em> mod 7<br><em>k</em> = [<em>year</em> / 100]<br><em>p</em> = [(13 + 8<em>k</em>) / 25]<br><em>q</em> = [<em>k</em> / 4]<br><em>M</em> = (15 - <em>p</em> + <em>k</em> - <em>q</em>) mod 30<br><em>N</em> = (4 + <em>k</em> - <em>q</em>) mod 7<br><em>d</em> = (19<em>a</em> + <em>M</em>) mod 30<br><em>e</em> = (2<em>b</em> + 4<em>c</em> + 6<em>d</em> + <em>N</em>) mod 7</p><ul><li><p>Easter is on 22 + <em>d</em> + <em>e</em> March or <em>d</em> + <em>e</em> - 9 April</p></li><li><p>Exception 1: if <em>d</em> = 29 and <em>e</em> = 6, Easter is on 19 April rather than 26 April</p></li><li><p>Exception 2: if <em>d</em> = 28 and <em>e</em> = 6 and (11<em>M</em> + 11) mod 30 &lt; 19, Easter is on 18 April rather than 25 April</p></li></ul><p>What is better? The conciseness of this math? Or the long variable names and splitting into functions, that makes it much more self-explanatory? I guess that the answer is &#8220;it depends&#8221;. Still, I think that math has too much emphasis on conciseness. I often read a paper and I wonder &#8220;what did we say <em>M</em> is?&#8221; and go some pages back to remember. Maybe math should take some ideas from programming and relax the rule of using single-letter variables. But of course it&#8217;s hard to break with centuries of tradition.</p>]]></content:encoded></item><item><title><![CDATA[Splitting in smaller functions]]></title><description><![CDATA[After fixing variable names, it's the next step towards improving readability]]></description><link>https://antonischristofides.substack.com/p/splitting-in-smaller-functions</link><guid isPermaLink="false">https://antonischristofides.substack.com/p/splitting-in-smaller-functions</guid><dc:creator><![CDATA[Antonis Christofides]]></dc:creator><pubDate>Wed, 26 May 2021 07:47:39 GMT</pubDate><enclosure url="https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/684e1d38-fcaa-48c2-a9c3-966243d8ae38_3984x2654.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>One of the mistakes I made when writing the Easter program was that I chose to write it in JavaScript. The reason I made this choice was so that you could easily run it in your browser.</p><p>It turns out that running it isn&#8217;t that important. What <em>is</em> important is for readers to be able to read it. While Python is easy for uninitiated to read, JavaScript is much less so, not because it&#8217;s a worse language, but because it has variable declarations; some people will say that this is a good thing, but it definitely creates some noise.</p><p>This shows that there&#8217;s no such thing as a language that is universally better than other languages. Which one to choose depends. <a href="https://antonischristofides.substack.com/p/which-programming-language-is-best">I&#8217;ve written about this in the past</a>.</p><p>In any case, after <a href="https://antonischristofides.substack.com/p/improving-variable-names-in-the-easter">fixing the variable names</a>, and before going on to improve its readability further by splitting it in smaller functions, I rewrote it in Python. You can see it (split in smaller functions) <a href="https://github.com/aptiko/easter/blob/1ea95ca583370f1ae59e6a2b58490ad641e52a9b/easter.py">here</a>. Here&#8217;s an extract:</p><pre><code>def calculate(self):
    self.find_days_from_equinox_to_full_moon()
    self.find_days_from_full_moon_to_sunday()
    self.find_easter_sunday()</code></pre><p>While the program is getting much better, it still has many improvements that need to be made. But the thing is, it&#8217;s quite long.  More on this next time.</p>]]></content:encoded></item><item><title><![CDATA[Improving variable names in the Easter program]]></title><description><![CDATA[Just with a few changes in names the algorithm starts making sense]]></description><link>https://antonischristofides.substack.com/p/improving-variable-names-in-the-easter</link><guid isPermaLink="false">https://antonischristofides.substack.com/p/improving-variable-names-in-the-easter</guid><dc:creator><![CDATA[Antonis Christofides]]></dc:creator><pubDate>Wed, 19 May 2021 10:21:22 GMT</pubDate><enclosure url="https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/077abd7e-ec9f-4753-8deb-20f4a528a364_4618x3047.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A few posts ago I showed you <a href="https://antonischristofides.substack.com/p/cleaning-up-the-easter-program">a program that calculates</a> the date of Easter. The program closely followed <a href="https://antonischristofides.substack.com/p/easter-algorithms">Gauss&#8217;s Easter algorithm</a>.</p><ul><li><p>Did you understand the program clearly? <strong>No</strong>.</p></li><li><p>Did you have a clue what&#8217;s going on? <strong>No</strong>.</p></li></ul><p>In the end of this post I&#8217;m showing you that very same program with only two changes:</p><ol><li><p>I&#8217;ve renamed most of the variables.</p></li><li><p>I&#8217;ve moved some variable definitions so that they&#8217;re nearer to where they&#8217;re being used.</p></li></ol><p>Let&#8217;s consider the same two questions:</p><ul><li><p>Do you understand the program clearly? <strong>Still no.</strong></p></li><li><p>Do you have a clue what&#8217;s going on? <strong>Yes!</strong></p></li></ul><p>Just by renaming a few variables you now have a clue what&#8217;s going on without needing to study Gauss&#8217;s paper.</p><p>Of course it&#8217;s less concise than what it was, but it&#8217;s our time and brain power that are in scarcity rather than ink and paper, much less storage bytes.</p><p>However, it still needs much improvement. Anyway, here is its current form:</p><pre><code>const DAYS_IN_12_MOONS = 12 * 29.5;
const DIFF_BETWEEN_12_MOONS_AND_ONE_YEAR = 365 - DAYS_IN_12_MOONS;

function getEasterDate(year) {
  let month;
  let dayOfMonth;

  const yearNumberInMetonicCycle = year % 19;
  const century = Math.floor(year / 100);
  const p = Math.floor((13 + 8 * century) / 25);
  const quadricentennial = Math.floor(century / 4);
  const M = (15 - p + century - quadricentennial) % 30;
  const daysFromEquinoxToFullMoon = (
    (
      (30 - DIFF_BETWEEN_12_MOONS_AND_ONE_YEAR)
      * yearNumberInMetonicCycle + M
    ) % 30
  );

  const b = year % 4;
  const c = year % 7;
  const N = (4 + century - quadricentennial) % 7;
  const daysFromFullMoonToSunday = (
    2 * b + 4 * c + 6 * daysFromEquinoxToFullMoon + N
  ) % 7;

  const exception1 = (
    daysFromEquinoxToFullMoon === 29
    &amp;&amp; daysFromFullMoonToSunday === 6
  );
  const exception2 = (
    daysFromEquinoxToFullMoon === 28
    &amp;&amp; daysFromFullMoonToSunday === 6
    &amp;&amp; (11 * M + 11) % 30 &lt; 19
  );
  if (exception1) {
    month = 4;
    dayOfMonth = 19;
  } else if (exception2) {
    month = 4;
    dayOfMonth = 18;
  } else {
    month = 3;
    dayOfMonth = (
      22 + daysFromEquinoxToFullMoon + daysFromFullMoonToSunday
    );
    if (dayOfMonth &gt; 31) {
      month = 4;
      dayOfMonth -= 31;
    }
  }
  return [month, dayOfMonth];
}</code></pre>]]></content:encoded></item><item><title><![CDATA[Testing the Easter program—part 2]]></title><description><![CDATA[FAQ on the testing code]]></description><link>https://antonischristofides.substack.com/p/testing-the-easter-programpart-2</link><guid isPermaLink="false">https://antonischristofides.substack.com/p/testing-the-easter-programpart-2</guid><dc:creator><![CDATA[Antonis Christofides]]></dc:creator><pubDate>Tue, 18 May 2021 07:25:01 GMT</pubDate><enclosure url="https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/6f8f186d-cd2b-4484-8007-ff11e128e1d2_4440x3552.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>You might have some questions upon seeing <a href="https://antonischristofides.substack.com/p/testing-the-easter-programpart-1">the tests I wrote for my Easter program</a> (I include these tests for reference at the end of this post).</p><p><strong>There are only seven tests. Are they enough?</strong></p><p>Maybe. To be exhaustive we&#8217;d need to write 5.7 million tests (Easter dates repeat after that, or so they say), and most models have infinite cases. Normally what we do is try to catch the edge cases and get going. At some point we may discover a bug in another edge case, so we add another test. And so the story goes.</p><p><strong>How do you find the expected result? How do you know that on 1598 the Easter was on 22 March?</strong></p><p>In this particular case I used another Easter program (<a href="https://manpages.debian.org/buster/bsdmainutils/ncal.1.en.html">ncal</a>) that I believe to be correct. The person who writes the first such program needs to test it by manually implementing the Church&#8217;s method to determine the expected results.</p><p>If your model is novel and you have nothing to compare it to, the best way to test the code is to have your associate solve the test case by hand, or in Excel, or in some other way, and sit down together to work out any differences between his results and your results. While this is time consuming, it&#8217;s exciting work, and you will have a rewarding feeling of trusting your code (and your model) when you&#8217;re done.</p><p>Finally, if you have code without automated tests, but you have used it for years and trust it, you can use it to solve the test cases and assume they&#8217;re correct. This is useful if you want to refactor the code but are afraid you might break something.</p><p><strong>The testing code looks very verbose. Wouldn&#8217;t it have been better to create a table of expected results and loop over it to check?</strong></p><p>In general no. Tests must be dead simple, without loops or ifs.</p><p>In this particular case, I think creating a table and a loop would have made sense. But in the thousands of tests I&#8217;ve written, I don&#8217;t recall ever having done anything like this. If I had shown you a table, it would have been hard to convince you that this is only a rare exception. I thus wrote the tests in the normal way.</p><div><hr></div><pre><code>test('earliest possible date', () =&gt; {
  expect(getEasterDate(1598)).toEqual([3, 22]);
});

test('latest possible date', () =&gt; {
  expect(getEasterDate(1666)).toEqual([4, 25]);
});

test('19 April special case where d = 29 and e = 6', () =&gt; {
  expect(getEasterDate(1609)).toEqual([4, 19]);
});

test('non-special 19 April', () =&gt; {
  expect(getEasterDate(1615)).toEqual([4, 19]);
});

test('18 April special case where d = 28 and e = 6 and more', () =&gt; {
  expect(getEasterDate(1954)).toEqual([4, 18]);
});

test('non-special 18 April', () =&gt; {
  expect(getEasterDate(1965)).toEqual([4, 18]);
});

test('correct p', () =&gt; {
  expect(getEasterDate(4200)).toEqual([4, 20]);
});</code></pre><p></p>]]></content:encoded></item><item><title><![CDATA[Testing the Easter program—part 1]]></title><description><![CDATA[Before improving the main code, it's important to have automated tests]]></description><link>https://antonischristofides.substack.com/p/testing-the-easter-programpart-1</link><guid isPermaLink="false">https://antonischristofides.substack.com/p/testing-the-easter-programpart-1</guid><dc:creator><![CDATA[Antonis Christofides]]></dc:creator><pubDate>Mon, 17 May 2021 11:06:30 GMT</pubDate><enclosure url="https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/3144cfd9-238a-4b06-9c4b-35119d4bd689_1920x1280.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I&#8217;m going to experiment with the <a href="https://antonischristofides.substack.com/p/cleaning-up-the-easter-program">Gauss Easter program</a> by trying to make it understandable without comments and without needing to explain it. Before that, I need to <a href="https://antonischristofides.substack.com/p/how-to-test-your-code">write some tests</a>.</p><p>The problem is I will be changing the code. How will I know I haven&#8217;t broken something? By going to the web interface and trying it out? This would be tedious and wouldn&#8217;t work well. Instead, I wrote a few automated tests. All I do now is enter a command on my terminal. It runs the tests, and after two seconds it tells me they passed.</p><p>Here are the tests, which you can probably understand easily even if you don&#8217;t know this language:</p><pre><code>test('earliest possible date', () =&gt; {
  expect(getEasterDate(1598)).toEqual([3, 22]);
});

test('latest possible date', () =&gt; {
  expect(getEasterDate(1666)).toEqual([4, 25]);
});

test('19 April special case where d = 29 and e = 6', () =&gt; {
  expect(getEasterDate(1609)).toEqual([4, 19]);
});

test('non-special 19 April', () =&gt; {
  expect(getEasterDate(1615)).toEqual([4, 19]);
});

test('18 April special case where d = 28 and e = 6 and more', () =&gt; {
  expect(getEasterDate(1954)).toEqual([4, 18]);
});

test('non-special 18 April', () =&gt; {
  expect(getEasterDate(1965)).toEqual([4, 18]);
});

test('correct p', () =&gt; {
  expect(getEasterDate(4200)).toEqual([4, 20]);
});</code></pre>]]></content:encoded></item><item><title><![CDATA[Cleaning up the Easter program]]></title><description><![CDATA[Don't add features to your scientific code (yet); clean it up first]]></description><link>https://antonischristofides.substack.com/p/cleaning-up-the-easter-program</link><guid isPermaLink="false">https://antonischristofides.substack.com/p/cleaning-up-the-easter-program</guid><dc:creator><![CDATA[Antonis Christofides]]></dc:creator><pubDate>Wed, 12 May 2021 14:06:04 GMT</pubDate><enclosure url="https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/8fffeb1a-c84a-4bff-9d6d-52eac3c0073f_2994x2227.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>What I like about <a href="https://antonischristofides.substack.com/p/implementing-the-easter-algorithm">my Easter calculation program</a> is that it shows how quickly scientific code becomes a mess. Whenever you reach the stage where a program starts giving good results, you say &#8220;Yes!&#8221; and then you start adding more features, when you should stop and clean the code instead.</p><p>In fact, I started to add more features to it before it was even ready. I should have written a purely Gregorian version, but I incorporated Julian before I even started. Now that I understand my mistake I&#8217;ll undo it. I&#8217;ll just throw away all Julian/Orthodox code, which is about 25% of all code.</p><p>The revised function (shown below) is also confusing, but at least it looks almost identical to <a href="https://antonischristofides.substack.com/p/easter-algorithms">Gauss&#8217;s algorithm</a> (that is, the algorithm is also confusing). My seemingly impossible task is to make the program understandable without comments and without needing to explain it. But before that we need to write some tests, coming in my next post.</p><pre><code>function getEasterDate(year) {
  let month;
  let dayOfMonth;

  const a = year % 19;
  const b = year % 4;
  const c = year % 7;
  const k = Math.floor(year / 100);
  const p = Math.floor((13 + 8 * k) / 25);
  const q = Math.floor(k / 4);
  const M = (15 - p + k - q) % 30;
  const N = (4 + k - q) % 7;
  const d = (19 * a + M) % 30;
  const e = (2 * b + 4 * c + 6 * d + N) % 7;
  if (d === 29 &amp;&amp; e === 6) {
    month = 4;
    dayOfMonth = 19;
  } else if (d === 28 &amp;&amp; e === 6 &amp;&amp; (11 * M + 11) % 30 &lt; 19) {
    month = 4;
    dayOfMonth = 18;
  } else {
    month = 3;
    dayOfMonth = 22 + d + e;
    if (dayOfMonth &gt; 31) {
      month = 4;
      dayOfMonth -= 31;
    }
  }
  return [month, dayOfMonth];
}</code></pre>]]></content:encoded></item><item><title><![CDATA[Implementing the Easter algorithm]]></title><description><![CDATA[A simple JavaScript program that illustrates how scientific code becomes a mess]]></description><link>https://antonischristofides.substack.com/p/implementing-the-easter-algorithm</link><guid isPermaLink="false">https://antonischristofides.substack.com/p/implementing-the-easter-algorithm</guid><dc:creator><![CDATA[Antonis Christofides]]></dc:creator><pubDate>Tue, 11 May 2021 11:22:05 GMT</pubDate><enclosure url="https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/e1319664-f110-4298-a935-610cf499485e_543x204.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I implemented <a href="https://antonischristofides.substack.com/p/easter-algorithms">Gauss&#8217;s Easter algorithm</a> in JavaScript. You can play with the program at <a href="https://easter.antonischristofides.com/">https://easter.antonischristofides.com/</a> and find the date in any year you like (but years prior to 1582 might not work correctly, and the result wouldn&#8217;t make sense anyway).</p><p>The heart of the program is the `getEasterDate()` function, which I include below. I wrote it quickly and it suffers from <a href="https://antonischristofides.substack.com/p/why-code-sucks">the problems most scientific code suffers</a>. Essentially it&#8217;s hard to understand. But the problem is that <a href="https://antonischristofides.substack.com/p/easter-algorithms">the algorithm itself</a> is hard to understand. Can we make the algorithm and the program easier to understand? I will start exploring this question in my next post.</p><p>Here is the boring code I promised (the full thing is at <a href="https://github.com/aptiko/easter">https://github.com/aptiko/easter</a>):</p><pre><code>function getEasterDate(year, type) {
  let month;
  let dayOfMonth;
  let M;
  let N;

  const a = year % 19;
  const b = year % 4;
  const c = year % 7;
  if (['julian', 'orthodox'].includes(type)) {
    M = 15;
    N = 6;
  } else {
    const k = Math.floor(year / 100);
    const p = Math.floor((13 + 8 * k) / 25);
    const q = Math.floor(k / 4);
    M = (15 - p + k - q) % 30;
    N = (4 + k - q) % 7;
  }
  const d = (19 * a + M) % 30;
  const e = (2 * b + 4 * c + 6 * d + N) % 7;
  if (d === 29 &amp;&amp; e === 6) {
    month = 4;
    dayOfMonth = 19;
  } else if (d === 28 &amp;&amp; e === 6 &amp;&amp; (11 * M + 11) % 30 &lt; 19) {
    month = 4;
    dayOfMonth = 18;
  } else {
    month = 3;
    dayOfMonth = 22 + d + e;
  }
  if (dayOfMonth &gt; 31) {
    month = 4;
    dayOfMonth -= 31;
  }
  if (type === 'orthodox') {
    dayOfMonth += julianDifference(year);
  }
  if (dayOfMonth &gt; monthDays(month)) {
    dayOfMonth -= monthDays(month);
    month += 1;
  }
  return [month, dayOfMonth];
}</code></pre>]]></content:encoded></item><item><title><![CDATA[Easter algorithms]]></title><description><![CDATA[A problem that has fascinated mathematicians for centuries]]></description><link>https://antonischristofides.substack.com/p/easter-algorithms</link><guid isPermaLink="false">https://antonischristofides.substack.com/p/easter-algorithms</guid><dc:creator><![CDATA[Antonis Christofides]]></dc:creator><pubDate>Mon, 10 May 2021 09:29:44 GMT</pubDate><enclosure url="https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/2f9bbb1c-ab9b-4007-8742-8de4f4343443_4287x2858.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><a href="https://antonischristofides.substack.com/p/easter">Determining the date of Easter</a> is a somewhat silly thing&#8212;you just get the Church&#8217;s tables and do some simple arithmetic. Despite that, the problem has fascinated mathematicians for centuries. Just search Google Scholar for &#8220;date of Easter&#8221; to get an idea. In fact, there exists <a href="https://www.jstor.org/stable/41134247">a paper</a> devoted to the <em>history</em> of such algorithms.</p><p>Gauss seems to be the first to have created <a href="http://webdoc.sub.gwdg.de/ebook/e/2005/gausscd/html/Osterformel/Seite1.htm">an algorithm in 1800</a>, which he republished with fixes in 1816. This is Gauss&#8217;s 1816 algorithm:</p><p><em>a</em> = <em>year</em> mod 19<br><em>b</em> = <em>year</em> mod 4<br><em>c</em> = <em>year</em> mod 7<br><em>k</em> = [<em>year</em> / 100]<br><em>p</em> = [(13 + 8<em>k</em>) / 25]<br><em>q</em> = [<em>k</em> / 4]<br><em>M</em> = (15 - <em>p</em> + <em>k</em> - <em>q</em>) mod 30<br><em>N</em> = (4 + <em>k</em> - <em>q</em>) mod 7<br><em>d</em> = (19<em>a</em> + <em>M</em>) mod 30<br><em>e</em> = (2<em>b</em> + 4<em>c</em> + 6<em>d</em> + <em>N</em>) mod 7</p><ul><li><p>Easter is on 22 + <em>d</em> + <em>e</em> March or <em>d</em> + <em>e</em> - 9 April</p></li><li><p>Exception 1: if <em>d</em> = 29 and <em>e</em> = 6, Easter is on 19 April rather than 26 April</p></li><li><p>Exception 2: if <em>d</em> = 28 and <em>e</em> = 6 and (11<em>M</em> + 11) mod 30 &lt; 19, Easter is on 18 April rather than 25 April</p></li></ul>]]></content:encoded></item><item><title><![CDATA[Easter]]></title><description><![CDATA[How is the Easter date determined?]]></description><link>https://antonischristofides.substack.com/p/easter</link><guid isPermaLink="false">https://antonischristofides.substack.com/p/easter</guid><dc:creator><![CDATA[Antonis Christofides]]></dc:creator><pubDate>Thu, 06 May 2021 11:52:14 GMT</pubDate><enclosure url="https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/40e2447b-7393-4165-80f5-5b6f9055cae1_3000x2000.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I&#8217;ve been away for the Orthodox Easter, which was last Sunday. I thought it&#8217;s a good time to deal with the age-old question: how is the Easter date determined?</p><p>Easter is, supposedly, on the Sunday after the first full Moon of the spring, where the spring supposedly starts on the equinox. But people in the Eastern Orthodox countries can see that, more often than not, this is not the case. Acute observers will notice that, sometimes, the Catholic/Protestant Easter is also off, such as in 2019, when the equinox was on 20 March 21:58 UTC, the full Moon was a few hours later, on 21 March 01:43 UTC, and yet Easter was on 21 April.</p><p>What happens is that the Church didn&#8217;t want to need to ask an astronomer each time. Especially until a few centuries ago, an annual announcement by the head of the Church would be hard to communicate to remote places. So they devised a method with which Easter can be calculated easily by anyone. Here are the details for the Julian Easter (which is the one celebrated by the Eastern Orthodox Church):</p><ul><li><p>It is assumed that the day of equinox is always 21 March (which in the Julian calendar is now off by 13 days, i.e. it is 3 April).</p></li><li><p>It is assumed that, every 19 years, the Moon phases recur at the same day of the year (the &#8220;Metonic cycle&#8221;).</p></li><li><p>A table (with 19 entries) provides the full Moon date for each of these 19 years.</p></li></ul><p>The Gregorian Easter is calculated in a similar manner, but it is more accurate, e.g. it has a provision for the fact that the Metonic cycle is off by roughly one day per century. Interestingly, the Julian calendar as a whole is off by roughly one day per century, and that error partially cancels out the Metonic cycle&#8217;s error. As a result, the Julian Easter&#8217;s &#8220;full Moon&#8221; is off by less than a week, which is why sometimes the Gregorian and the Julian Easter coincide.</p>]]></content:encoded></item></channel></rss>