Pic Micro, Arduino, Atmel, Microchip, Freescale, Texas Instrument, ecc. Strumenti di sviluppo, firmware e progetti.
Avatar utente
da GioRock
#4999
Dovremo avere la versione definitiva :roll: con le ultime correzioni, adesso possiamo dire che ci siamo, prossimamente vedrò di applicare una maggiore ottimizzazione del codice:

MIKROBASIC CODE:

Codice: Seleziona tutto'-----------------------------------------------------------------
 PROGRAM EasterDayCalc ' MikroBasic
'-----------------------------------------------------------------

CONST GREGORIAN AS BYTE = 0
CONST JULIAN AS BYTE = 1

SUB FUNCTION EasterDay(DIM Year AS WORD, CT AS BYTE) AS WORD
DIM m AS WORD
DIM n AS WORD
DIM Y AS WORD
DIM a AS WORD
DIM b AS WORD
DIM c AS WORD
DIM d AS WORD
DIM e AS WORD
DIM ED AS WORD

    Y = Year

    IF CT = GREGORIAN THEN
        m = 24
        n = 5
    ELSE
        m = 15
        n = 6
    ENF IF
   
    a = Y MOD 19
    b = Y MOD 4
    c = Y MOD 7
    d = (19 * a + m) MOD 30
    e = (2 * b + 4 * c + 6 * d + n) MOD 7
   
    ED = 22 + d + e
   
    IF ED <= 31 THEN
        ED = ED * $100 + 3 ' Marzo
    ELSE
        ED = (d + e - 9) * $100 + 4 ' Aprile
    END IF

    IF CT = GREGORIAN THEN
        IF ED = $1A04 THEN ED = $1304 ' Il 26 Aprile diventa il 19 Aprile
        IF (ED = $1904) AND (d = 28) AND (e = 6) AND (a > 10) THEN ED = $1204 ' Il 25 Aprile è sempre il 18 Aprile se...
    END IF

    result = ED ' ritorna il giorno insieme al mese
                ' sotto forma di una WORD (max. 7'940)
                ' 31 * $100 + 4 - 2 BYTE GIORNO + 2 BYTE MESE
                ' MSB |G|G|M|M| LSB

END SUB

main:
DIM Pasqua AS WORD
DIM GiornoDiPasqua AS BYTE
DIM MeseDiPasqua AS BYTE

    Pasqua = EasterDay(2017, JULIAN)
    GiornoDiPasqua = byte((Pasqua / $100) MOD $100)
    MeseDiPasqua = byte(Pasqua MOD $100)

END.



MIKROC CODE:

Codice: Seleziona tutto//-----------------------------------------------------------------
// PROGRAM EasterDayCalc - MikroC
//-----------------------------------------------------------------

enum CalendarType {
    GREGORIAN,
    JULIAN
};

unsigned EasterDay(unsigned Year, CalendarType CT) {
unsigned m;
unsigned n;
unsigned Y;
unsigned a;
unsigned b;
unsigned c;
unsigned d;
unsigned e;
unsigned ED;

    Y = Year;
   
    m = (CT == GREGORIAN ? 24 : 15);
    n = (CT == GREGORIAN ? 5 : 6);
   
    a = Y % 19;
    b = Y % 4;
    c = Y % 7;
    d = (19 * a + m) % 30;
    e = (2 * b + 4 * c + 6 * d + n) % 7;
   
    ED = 22 + d + e;
   
    if (ED <= 31) {
        ED = ED * 0x100 + 3; // Marzo
    } else {
        ED = (d + e - 9) * 0x100 + 4; // Aprile
    }

    if (CT == GREGORIAN) {
        if (ED == 0x1A04) ED = 0x1304; // Il 26 Aprile diventa il 19 Aprile
        if ((ED == 0x1904) && (d == 28) && (e == 6) && (a > 10)) ED = 0x1204; // Il 25 Aprile è sempre il 18 Aprile se...
    }
   
    return ED; // ritorna il giorno insieme al mese
               // sotto forma di una UNSIGNED (max. 7'940)
               // 31 * 0x100 + 4 - 2 BYTE GIORNO + 2 BYTE MESE
               // MSB |G|G|M|M| LSB

}

void main() {
unsigned Pasqua;
unsigned short GiornoDiPasqua;
unsigned short MeseDiPasqua;

    Pasqua = EasterDay(2017, GREGORIAN);
    GiornoDiPasqua = (unsigned short)((Pasqua / 0x100) % 0x100);
    MeseDiPasqua = (unsigned short)(Pasqua % 0x100);


}

#5000
Per il calendario GREGORIANO si dovrebbe usare una tabella apposita per il valori di m e n, infatti ogni Secolo a venire, questi cambiano e influiscono sul risultato del calcolo, per ora siamo a posto fino al 2099, per allora saranno problemi dei posteri, tenete conto che il tutto deve stare in un uP e quindi non possiamo esagerare con il contenuto... :rad:

Codice: Seleziona tutto   Anni   M  N

1583-1699 22 2
1700-1799 23 3
1800-1899 23 4
1900-2099 24 5
2100-2199 24 6
2200-2299 25 0
2300-2399 26 1
2400-2499 25 1


Questi i Nuovi Calcoli con la Nuova Funzione:


Codice: Seleziona tuttoGREGORIANO     GIULIANO

23/04/2000    17/04/2000
15/04/2001    02/04/2001
31/03/2002    22/04/2002
20/04/2003    14/04/2003
11/04/2004    29/03/2004
27/03/2005    18/04/2005
16/04/2006    10/04/2006
08/04/2007    26/03/2007
23/03/2008    14/04/2008
12/04/2009    06/04/2009
04/04/2010    22/03/2010
24/04/2011    11/04/2011
08/04/2012    02/04/2012
31/03/2013    22/04/2013
20/04/2014    07/04/2014
05/04/2015    30/03/2015
27/03/2016    18/04/2016
16/04/2017    03/04/2017
01/04/2018    26/03/2018
21/04/2019    15/04/2019
12/04/2020    06/04/2020
04/04/2021    19/04/2021
17/04/2022    11/04/2022
09/04/2023    03/04/2023
31/03/2024    22/04/2024
20/04/2025    07/04/2025
05/04/2026    30/03/2026
28/03/2027    19/04/2027
16/04/2028    03/04/2028
01/04/2029    26/03/2029
21/04/2030    15/04/2030
13/04/2031    31/03/2031
28/03/2032    19/04/2032
17/04/2033    11/04/2033
09/04/2034    27/03/2034
25/03/2035    16/04/2035
13/04/2036    07/04/2036
05/04/2037    23/03/2037
25/04/2038    12/04/2038
10/04/2039    04/04/2039
01/04/2040    23/04/2040
21/04/2041    08/04/2041
06/04/2042    31/03/2042
29/03/2043    20/04/2043
17/04/2044    11/04/2044
09/04/2045    27/03/2045
25/03/2046    16/04/2046
14/04/2047    08/04/2047
05/04/2048    23/03/2048
18/04/2049    12/04/2049
10/04/2050    04/04/2050
02/04/2051    24/04/2051
21/04/2052    08/04/2052
06/04/2053    31/03/2053
29/03/2054    20/04/2054
18/04/2055    05/04/2055
02/04/2056    27/03/2056
22/04/2057    16/04/2057
14/04/2058    01/04/2058
30/03/2059    21/04/2059
18/04/2060    12/04/2060
10/04/2061    28/03/2061
26/03/2062    17/04/2062
15/04/2063    09/04/2063
06/04/2064    31/03/2064
29/03/2065    13/04/2065
11/04/2066    05/04/2066
03/04/2067    28/03/2067
22/04/2068    16/04/2068
14/04/2069    01/04/2069
30/03/2070    21/04/2070
19/04/2071    06/04/2071
10/04/2072    28/03/2072
26/03/2073    17/04/2073
15/04/2074    09/04/2074
07/04/2075    25/03/2075
19/04/2076    13/04/2076
11/04/2077    05/04/2077
03/04/2078    25/04/2078
23/04/2079    10/04/2079
07/04/2080    01/04/2080
30/03/2081    21/04/2081
19/04/2082    06/04/2082
04/04/2083    29/03/2083
26/03/2084    17/04/2084
15/04/2085    02/04/2085
31/03/2086    25/03/2086
20/04/2087    14/04/2087
11/04/2088    05/04/2088
03/04/2089    18/04/2089
16/04/2090    10/04/2090
08/04/2091    26/03/2091
30/03/2092    14/04/2092
12/04/2093    06/04/2093
04/04/2094    29/03/2094
24/04/2095    11/04/2095
15/04/2096    02/04/2096
31/03/2097    22/04/2097
20/04/2098    14/04/2098
12/04/2099    30/03/2099

double ringraziano
#5002
Perchè dopo l'algoritmo di Gauss non provi anche il Computus (esatto al 100% per le pasque gregoriane) che l'astronomo Harold Spencer Jones pubblicò nel 1922?
http://misterpalomar.blogspot.it/2011/0 ... jones.html

Da uno sguardo sommario il metodo si presta bene per essere messo su un micro visto che usa solo quozienti e resti (divisione per intero e divisione per modulo). Oltretutto non ha bisogno di tabelle: dato l'anno fornisce giorno e mese in 10 passi.
In giornata lo provo per vedere se funziona senza le correzioni per le due date con gli if ( 19/4/2076 e 18/4/2049).
GioRock ringraziano
#5004
Update.
Il computus di Jones funziona perfettamente su arduino usando variabili <int16_t> e gli operatori di divisione / e %.
Una variabile <uint16_t> serve invece per fare il merge di giorno e mese in un unico pacchetto di ritorno dalla funzione. Non ho verificato se in qualche passaggio intermedio si creano valori negativi, in tal caso l'uso di variabili <int16_t> col segno nei conti intermedi sarebbe indispensabile invece che opzionale.
Ovviamente i risultati sono validi solo dal 1583 in poi per la sola pasqua cattolica e riformata, per quella ortodossa col calendario giuliano serve invece il computus di gauss con i coefficienti 15 e 6.
Tutto questo ambaradan solo perchè il moto degli gli astri è parecchio irregolare e calcolare gli equinozi e le lunazioni in modo sufficientemente preciso è un massacro di conteggi.....
GioRock ringraziano
Avatar utente
da GioRock
#5005
Prova questa di Ian Taylor solo GREGORIANO, l'ho testata su PC e funge ottimamente:

Codice: Seleziona tutto
// Python - IAN TAYLOR EASTER DAY

    a = year % 19
    b = year >> 2
    c = b // 25 + 1
    d = (c * 3) >> 2
    e = ((a * 19) - ((c * 8 + 5) // 25) + d + 15) % 30
    e += (29578 - a - e * 32) >> 10
    e -= ((year % 7) + b - d + e + 2) % 7
    d = e >> 5

    day = e - d * 31
    month = d + 3



P.S. I doppi segni di divisione indicano che questa deve ritornare solamente la parte intera, in C si usa la funzione div che restituisce appunto una struttura del tipo <div_t>...
#5008
Nuova Funzione del Calcolo della Pasqua con la formula di Ian Taylor:

MIKROC CODE:
Codice: Seleziona tuttounsigned RoundDown(float X) {
    return (unsigned)(((X - 0.5) * 100 + 1 / 2) / 100);
}

unsigned GregorianEasterDayIT(unsigned Year) {
unsigned a;
unsigned b;
unsigned c;
unsigned d;
unsigned e;
unsigned Y;
unsigned ED
 
//  IAN TAYLOR EASTER DAY

    Y = Year;

    a = Y % 19;
    b = Y >> 2;
    c = RoundDown((float)(b / 25)) + 1;
    d = (c * 3) >> 2;
    e = ((a * 19) - RoundDown((float)((c * 8 + 5) / 25)) + d + 15) % 30;
    e += (29578 - a - e * 32) >> 10;
    e -= ((Y % 7) + b - d + e + 2) % 7;
    d = e >> 5;

    ED = (unsigned)((e - d * 31) << 8) + (d + 3);

    return ED; // ritorna il giorno insieme al mese
               // sotto forma di una UNSIGNED (max. 7'940)
               // 31 * 0x100 + 4 - 2 BYTE GIORNO + 2 BYTE MESE
               // MSB |G|G|M|M| LSB


}

void main() {
unsigned Pasqua;
unsigned short GiornoDiPasqua;
unsigned short MeseDiPasqua;

    Pasqua = GregorianEasterDayIT(2017);
    GiornoDiPasqua = (unsigned short)((Pasqua / 0x100) % 0x100);
    MeseDiPasqua = (unsigned short)(Pasqua % 0x100);


}


Non ho voluto aggiungere le librerie Math del MikroC perché farebbero aumentare notevolmente la dimensione dell'eseguibile portandosi dietro tutta la parte relativa ai calcoli con le variabili double, infatti al posto di utilizzare div e floor, ho creato una funzione custom per l'arrotondamento delle divisioni che verranno eseguite con il normale operatore, poi sta a Voi fare le vostre scelte...
double ringraziano
#5009
A pagina 69 del testo Astronomical Algorithms di Jean Meeus che riporta il computo di Spencer Jones c'è anche il calcolo della pasqua Giuliana. Anche questo usa l'aritmetica modulare con soli numeri interi.

Codice: Seleziona tuttoJulian Easter
divide          by   Quotient   Remainder
the year x         4       -         a
the year x         7       -         b
the year x         19      -         c
19c + 15           30      -         d
2a + 4b - d +34     7      -         e
d + e + 114        31      f         g

f = number of the month (3= march, 4= april)
g+1 = day of the month  upon which Easter sunday falls

Ora la tua funzione doverebbe essere davvero completa!

ps. grazie al tuo post ho trovato il testo di Meeus con un mare di algoritmi astronomici, grazie davvero!
GioRock ringraziano
Avatar utente
da GioRock
#5010
Ottimo :D , probabilmente scavando potremo arrivare ad avere la formula perfetta per risparmiare memoria e cicli macchina!!!

Ho anche l'Algoritmo per calcolare il Ciclo Lunare con Ora e Data facendo riferimento al Calendario Giuliano, ma penso che sia troppo complessa da mettere in un uP, li bisogna anche tenere conto della posizione del luogo e della tipologia di ora utilizzata, sarebbe meglio a questo punto fare i calcoli col PC e inserire tutto in una memoria esterna per una lettura immediata...

Magari prossimamente si possono azzardare delle funzioni ottimizzate per questo Gadget da inserire in qualche orologio, al momento non trovo formule facili da poter cominciare la migrazione del Codice...
Dimmer su aspirazione

Ciao a tutti ho una ventola di aspirazione in came[…]

Visita il nostro canale telegram