Mi sono imbattuto nel sorgente per la funzione gmtime di Minix. Mi interessava il bit che calcolava il numero dell'anno da giorni a partire dall'epoca. Qui ci sono le budella di quel po ':Perché gmtime è implementato in questo modo?
http://www.raspberryginger.com/jbailey/minix/html/gmtime_8c-source.html
http://www.raspberryginger.com/jbailey/minix/html/loc__time_8h-source.html
#define EPOCH_YR 1970
#define LEAPYEAR(year) (!((year) % 4) && (((year) % 100) || !((year) % 400)))
#define YEARSIZE(year) (LEAPYEAR(year) ? 366 : 365)
int year = EPOCH_YR;
while (dayno >= YEARSIZE(year)) {
dayno -= YEARSIZE(year);
year++;
}
Sembra che l'algoritmo è O (n), dove n è la distanza dal dell'epoca. Inoltre, sembra che LEAPYEAR debba essere calcolato separatamente per ogni anno – decine di volte per le date attuali e molte altre per date lontane nel futuro. Ho avuto il seguente algoritmo per fare la stessa cosa (in questo caso dall'epoca ISO-9601 (anno 0 = 1 aC), piuttosto che UNIX epoca):
#define CYCLE_1 365
#define CYCLE_4 (CYCLE_1 * 4 + 1)
#define CYCLE_100 (CYCLE_4 * 25 - 1)
#define CYCLE_400 (CYCLE_100 * 4 + 1)
year += 400 * (dayno/CYCLE_400)
dayno = dayno % CYCLE_400
year += 100 * (dayno/CYCLE_100)
dayno = dayno % CYCLE_100
year += 4 * (dayno/CYCLE_4)
dayno = dayno % CYCLE_4
year += 1 * (dayno/CYCLE_1)
dayno = dayno % CYCLE_1
Questo viene eseguito in O (1) per qualsiasi data e sembra che dovrebbe essere più veloce anche per date ragionevolmente vicine al 1970.
Quindi, partendo dal presupposto che gli sviluppatori Minix sono persone intelligenti che hanno fatto a modo loro un motivo, e probabilmente conoscono un po 'più di C rispetto a me , perché?
Sembra * dovrebbe essere più veloce. Devi pensare alla tua architettura e alla velocità con cui certe istruzioni come moltiplicare sono e quanto è buono un predittore di branche che hai (la maggior parte sono molto buone). @jim mcnamara ha alcuni risultati interessanti. – BobbyShaftoe