--- title: "Easter" id: 71498 type: "computer_media" slug: "easter" url: "http://localhost/computer_media/easter/" markdown_url: "http://localhost/computer_media/easter.md" published_at: "2026-09-09T09:07:00+00:00" modified_at: "2026-09-09T09:07:01+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2026/09/easter-2.png" excerpt: "Calculate the exact date of Easter Sunday for any year from 1900 to 2099, using a modular-arithmetic algorithm with hard-coded corrections for known edge cases." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 2068" slug: "ts2068" taxonomy: "post_tag" url: "http://localhost/tag/ts2068/" model: - name: "Timex/Sinclair 2068" slug: "ts-2068" taxonomy: "model" url: "http://localhost/model/ts-2068/" indiv: - name: "Louis LaFerriere" slug: "louis-laferriere" taxonomy: "indiv" url: "http://localhost/indiv/louis-laferriere/" genre: - name: "Calendar" slug: "calendar" taxonomy: "genre" url: "http://localhost/type/calendar/" media_type: "Program" programmers: - name: "Louis LaFerriere" slug: "louis-laferriere" taxonomy: "indiv" url: "http://localhost/indiv/louis-laferriere/" download_url: "https://archive.org/download/timex-sinclair-software-archive/Easter%20(198x)(Laferriere%2C%20Louis)(TS2068)(US)(Program).zip" tsrun_member: "Easter (198x)(Laferriere, Louis)(TS2068)(US)(Program).tap" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2026/09/easter-2.png" - url: "http://localhost/wp-content/uploads/2026/09/easter.png" media_type_tags: "Calendar" --- # Easter This program calculates the date of Easter Sunday for any year between 1900 and 2099 using an algorithmic approach based on modular arithmetic. The core algorithm derives the Easter date through several intermediate variables—including a Metonic cycle value (A), an epact correction (B), and day-of-week offsets (Q, W)—before arriving at a day number relative to April 25. The program includes hard-coded corrections for 1974, 1984, and 1994 to patch known discrepancies in the algorithm. Input is accepted as a string via INPUT Y$ then converted with VAL, and a simple range check enforces the 1900–2099 boundary. The program loops to allow multiple year lookups within a single session. *** ### Program Structure The program is organized into a linear flow with a few branching subroutines. An introductory display at lines 20–180 is followed by the main input-validation-calculation-output loop running from line 190 onward. Line 9000 contains a `SAVE` with autostart. The major phases are: 1. Title screen and intro text (lines 10–180) 2. Year input and range validation (lines 190–380) 3. Easter date calculation (lines 390–550) 4. Result display (lines 560–790) 5. Repeat or quit prompt (lines 830–890) ### The Easter Algorithm The algorithm is a variant of an anonymous Gregorian Easter calculation that was commonly circulated in computing magazines. It uses the following intermediate values: | Variable | Meaning | | --- | --- | | `N` | Year offset from 1900 | | `A` | Year’s position in the 19-year Metonic cycle | | `B` | Epact correction term | | `M` | Paschal full moon day offset | | `Q` | Leap-year quarter correction | | `W` | Day-of-week offset | | `DE` | Final day offset from April 25 (negative = March) | The fractional-part trick is central to the algorithm: for example, `A = 19*(A - INT(A))` extracts the remainder of `N/19` without using MOD, since ZX81 BASIC lacks a modulo operator. The same technique is applied to compute `W`. ### Notable Techniques and Idioms - **String input for numbers:** Year is read as `Y$` and converted with `VAL(Y$)` at line 250, a common idiom to avoid direct numeric INPUT issues. - **Fractional-remainder arithmetic:** Modular reduction is performed via `X - INT(X)` patterns throughout, substituting for the absent MOD function. - **Floating-point guard:** Line 450 uses `4.00001` instead of `4` to prevent floating-point precision errors from causing `M` to be computed as a value fractionally below an integer. - **Conditional GOSUB:** Lines 470–500 form an unusual branching structure. If `X = 1`, execution jumps to line 500 (which sets `M = 0`) and then falls through to line 510 (the body that would have been reached via `GO SUB 510`). If `X ≠ 1`, `M` is assigned at line 480 and then `GO SUB 510` is called at line 490 — but the subroutine at 510 has no `RETURN`, meaning this behaves as a `GO TO`, not a proper subroutine. This is a latent bug. ### Hard-Coded Year Corrections Lines 740–760 apply manual patches for three specific years where the generic algorithm produces an incorrect result: - 1974 and 1984: day value incremented by 7 - 1994: day incremented by 7 then reduced by 31, and month changed to April These corrections suggest the base algorithm used here is an approximation that deviates from the full Gregorian Easter computation for certain exceptional years. ### Bugs and Anomalies - **Missing RETURN at line 510:**`GO SUB 510` at line 490 is never matched by a `RETURN`; execution simply falls through. If the subroutine were ever truly called (with a return address on the stack), a `RETURN` error would occur later. In practice the program runs correctly only because the fall-through path works as intended. - **Repeat-loop condition bug (line 860):** The second condition in `IF A$="Y" OR A$="Y"` is a copy-paste error — both branches test `"Y"` rather than `"Y"` and `"y"`. In effect, after a `PAUSE 200`, only uppercase `Y` will loop, even though lowercase `y` was allowed by the first condition. - **Line 500 reachable by fall-through and by jump:** After the `GO TO 500` at line 470 sets `M = 0`, execution continues at line 510 — which is correct. However, in the `X ≠ 1` branch, `GO SUB 510` at line 490 also continues at line 510, so `M` assigned at line 480 is retained. The logic is functionally correct despite the structural oddity. - **Line 550 computes a negative-biased offset:**`DE = INT(25 - M - W)` yields a day measured from April 25. Negative values indicate March dates, requiring the sign-based branching at lines 660–720 to reconstruct the actual calendar date. ## Source Code ``` 10 REM Received from Louis Laferriere. GFC 20 PRINT AT 2,5;"EASTER DATES CALCULATOR"''' 60 PRINT "THIS PROGRAM CALCULATES THE DATEOF 'EASTER SUNDAY' FOR ANY YEAR BETWEEN 1900 AND 2099" 90 PRINT :PRINT :PRINT :PRINT 180 PAUSE 260 190 CLS 200 PRINT :PRINT :PRINT 240 PRINT "YEAR REQUIRED "; 250 INPUT Y$:LET Y= VAL (Y$) 270 IF Y<1900 OR Y>2099 THEN GO TO 290 280 GO TO 390 290 CLS :PRINT :PRINT :PRINT "INVALID ENTRY" 330 PAUSE 300 340 CLS 380 GO TO 240 390 PRINT Y 400 LET N=Y-1900 410 LET A=N/19 420 LET A=19*(A- INT (A)) 430 LET B= INT ((7*A+1)/19) 440 LET M=0 450 LET M=(11*A+4.00001-B)/29 460 LET X=M- INT (M) 470 IF X=1 THEN GO TO 500 480 IF X <>1 THEN LET M=29*X 490 GO SUB 510 500 LET M=0 510 LET Q= INT (N/4) 520 LET W=(N+Q+31-M)/7 530 LET W=7*(W- INT (W)) 540 LET W= INT (W) 550 LET DE= INT (25-M-W) 560 CLS 570 PRINT :PRINT :PRINT :PRINT 620 PRINT "EASTER SUNDAY ";Y;" IS":PRINT :PRINT :PRINT 660 IF DE>0 THEN LET M$="APRIL" 670 IF DE<0 THEN LET M$="MARCH" 680 IF DE=0 THEN LET M$="MARCH 31" 690 IF DE=0 THEN GO TO 780 700 IF DE<-9 THEN LET DE=DE+9 710 IF DE<-9 THEN GO TO 700 720 IF DE<0 THEN LET D=31- ABS (DE) 730 IF DE>0 THEN LET D=DE 740 IF Y=1974 OR Y=1984 THEN LET D=D+7 750 IF Y=1994 THEN LET D=D+7-31 760 IF Y=1994 THEN LET M$="APRIL" 770 PAUSE 350 780 PRINT " ";M$;" ";D 790 PRINT :PRINT :PRINT 830 PRINT "WANT ANOTHER YEAR Y/N ?" 840 INPUT A$:PRINT A$ 860 IF A$="Y" OR A$="y" THEN PAUSE 200:IF A$="Y" OR A$="Y" THEN GO TO 190 880 IF A$="N" OR A$="n" THEN GO TO 920 890 PRINT :PRINT "INVALID REPLY":GO TO 830 920 CLS 9000 SAVE "easter.B1" LINE 1 ```