2013-02-28 9 views
8

Quando si calcola la differenza di millisecondo tra due oggetti DateTime, sembra sempre che venga restituito un numero in cui la parte decimale del numero è uguale al numero intero del numero. Ad esempio: 1235.1235Perché i millisecondi total times hanno le stesse cifre nelle parti integer e decimali?

Perché ciò accade? Sto facendo qualcosa di sbagliato? È una stranezza della lingua o una limitazione della granularità DateTime o qualcosa del genere?

Questo può essere dimostrato utilizzando il seguente codice:

 DateTime then = DateTime.Now; 
     Thread.Sleep(1234); 
     DateTime now = DateTime.Now; 
     TimeSpan taken = now - then; 
     string result = taken.TotalMilliseconds.ToString(CultureInfo.InvariantCulture); 
     //result = "1235.1235" 

come commentato da CodesInChaos:

DateTime` non è preciso a questo livello di precisione: vedi C# DateTime.Now precision

Tuttavia - che non spiega abbastanza questo comportamento.

+1

che probabilmente è solo la fortuna del sorteggio. inoltre: dai un'occhiata alla classe 'Stopwatch'. –

+2

Quante volte è sempre? –

+1

'DateTime.Now' * al meglio * ha una precisione millisecondo. In pratica è spesso solo 16ms. Sospetto che la parte frazionaria sia un artefatto di come windows (non .net) rappresenta le date internamente. – CodesInChaos

risposta

4

C'è una spiegazione tecnica per questo, non posso altrimenti dimostrare che spiega la tua osservazione. Di sicuro non ripro sulla mia macchina.

Per gli starter si sta osservando una cifra acustica, l'orologio del sistema operativo non è abbastanza preciso da fornire una precisione inferiore al millisecondo. Quindi assicurati di non fare affidamento sul loro valore per fare qualcosa di importante. Se si desidera misurare un intervallo con alta risoluzione, è necessario utilizzare invece il cronometro.

L'orologio del sistema operativo è interessato dagli aggiornamenti da un server orario. La maggior parte delle macchine sono configurate per contattare periodicamente lo time.windows.com per ricalibrare l'orologio. Questo elimina la deriva del clock, l'hardware della macchina in genere non è abbastanza buono da mantenere il tempo preciso per meglio di un secondo più di un mese. I cristalli a bassa tolleranza sono costosi e mai completamente senza deriva a causa della temperatura e degli effetti dell'invecchiamento. E un secondo intercalare viene inserito una volta ogni tanto per mantenere sincronizzati gli orologi con la rotazione rallentata del pianeta. L'ultimo si è schiantato un sacco di macchine Linux, google "Linux leap second bug" per una lettura divertente.

Ciò che conta è ciò che accade quando la macchina riceve un nuovo aggiornamento che richiede di regolare l'orologio. Windows fa non improvvisamente salta il valore di clock, che causa grossi problemi con i programmi che prestano attenzione all'orologio e si aspettano che aumenti in modo consistente in quantità prevedibili.

Invece, aggiunge un bit alla volta con ogni incremento di tick dell'orologio. In effetti, l'orologio funziona un po 'più lentamente o più velocemente, quindi gradualmente farà la differenza e tornerà ad essere accurato. Forse puoi vedere dove va, i microsecondi aggiunti in più sono proporzionali alla lunghezza dell'intervallo. Quindi vedere l'intervallo ripetuto nelle cifre del rumore è plausibile.

L'unico vero modo per dimostrare questa teoria è quello di pinvoke GetSystemTimeAdjustment(). Restituirà valori diversi da zero quando è in corso una regolazione temporale del sistema. E quindi pinvoke SetSystemTimeAdjustment() per disabilitarlo e osservare se questo fa la differenza nel valore che vedi. Oppure basta aspettare abbastanza a lungo fino a quando l'orologio non si è avvicinato, in modo che non venga più regolato.

+0

Quindi, se testato questo su una nuova installazione di Windows, 'GetSystemTimeAdjustment()' deve restituire zero e non si vedrebbe questo comportamento? –

+0

Probabilmente è il momento peggiore per farlo, sicuramente l'orologio è in pausa. Non collegare il cavo di rete. –

+0

interessante :-) Ho controllato i TimeAdjustment ed è abilitato - l'incremento è ritorna come 156001 zecche e non sembra variare. Per verificare, dovrò prenderlo in un momento diverso da zero per vedere se i risultati sono diversi. (Non sono riuscito a ottenere SetSystemTimeAdjustment per disabilitare la regolazione, quindi proverò più tardi.) – Kaine

Problemi correlati