2012-03-14 7 views
12

Le 2 righe successive aggiungono lo stesso importo alla stessa data e la parte relativa alla data dei risultati è la stessa, ma in qualche modo c'è differenza nella parte temporale!Problema AddDays .NET

(new DateTime(2000,1,3,18,0,0)).AddDays(4535); 
(new DateTime(2000,1,3,18,0,0)).AddMonths(149); 

si otterrà una differenza di 15 secondi, e con entrambi sono almeno roundable di giorni, non so il motivo per cui questo è accaduto, ma succede solo con AddDays, ma non AddMonths (anche con migliaia di mesi aggiunti)


Modifica 1

Così ho provato a fare un progetto di esempio, ma senza fortuna. Se eseguo il mio progetto principale e inserisco le linee di campionamento negli orologi, allora ottengo 2 valori separati, se faccio un nuovo inizio, il problema non c'è. Il progetto è 3.5, C#, vs2010, win7hp x64 (proj: x86). Sto cercando di riprodurlo anche in un nuovo piccolo progetto, scriverò di nuovo se ce l'ho.

Questi sono i miei risultati nel progetto principale (copeid dagli orologi!):

(new DateTime(2000, 1, 3, 18, 0, 0)).AddDays(4535).Ticks  
634743432153600000 long 

(new DateTime(2000, 1, 3, 18, 0, 0)).AddMonths(149).Ticks 
634743432000000000 long 

Edit 2

sono riuscito a restringere il campo ancora di più. Abbiamo un componente autoprodotto, una base di pannelli, che disegniamo su di esso con directx. Se lo faccio visibile = falso, che visible = true, che l'errore arriva, prima di visible = true (o show()), il calcolo è corretto. Ciò che nel mondo può essere lì, che il risultato ottiene qualcos'altro di una formula in cui non viene utilizzata alcuna variabile. La cultura non è influenzato nel componente ..

+0

Potrebbe essere un problema a causa del tipo di dati, poiché AddDays richiede un doppio. Sembra che la differenza dovrebbe essere molto meno di 15 secondi, però. Controlla http://en.wikipedia.org/wiki/Double_precision per vedere come si approssima semplicemente i valori. –

+1

Hai provato a invertire l'ordine delle chiamate al metodo per vedere se ottieni lo stesso risultato? Probabilmente non farà la differenza, ma sono curioso. –

+3

Non sono stato in grado di riprodurre questo (sul compilatore C# 4). Qual è il tuo ambiente? – SWeko

risposta

3

Questo è il risultato di DirectX che modifica in modo silenzioso la modalità di calcolo a virgola mobile della CPU per utilizzare sempre la precisione singola. Questo a volte viene fatto per le prestazioni: l'uso della precisione singola può essere un po 'più veloce rispetto all'utilizzo della doppia precisione. Vedere la descrizione del flag FpuPreserve nella documentazione MSDN per l'enumerazione di DirectX CreateFlags.

Il motivo per cui gli altri non sono in grado di riprodurre questo è perché non stanno facendo quelle chiamate DirectX.

L'argomento su AddDays è un double. Questo valore viene moltiplicato per un fattore di scala per ottenere il tempo in millisecondi. È questo calcolo che produce l'errore.

consideri:

double value = 4535; 
int scale = 86400000; 
long milliseconds = (long) ((value * scale) + ((value >= 0.0) ? 0.5 : -0.5)); 
long milliseconds2 = (long)((float)(value * scale) + ((value >= 0.0) ? 0.5 : -0.5)); 
Console.WriteLine(milliseconds2 - milliseconds); 

L'espressione per milliseconds2 contiene un cast float, che imita l'effetto di costringere DirectX calcoli singola precisione. Questo stamperà 15360, esattamente la differenza che trovi.

Al contrario, AddMonths accetta un numero intero e non utilizza aritmetica a virgola mobile. Quindi il risultato è esatto.

4

Qui danno lo stesso risultato:

var d1 = (new DateTime(2000, 1, 3, 18, 0, 0)).AddDays(4535).Ticks; 
var d2 = (new DateTime(2000, 1, 3, 18, 0, 0)).AddMonths(149).Ticks; 

d1 == d2 == 634.743.432 miliardi

(il Tick è il "quantum" interno del tempo di DateTime. E 'abbastanza breve. E' one ten-millionth of a second

io aggiungo che anche mono (un'implementazione indipendente NET) dà lo stesso risultato http://ideone.com/krySY (Ideone utilizza mono)

0.123.

Considerando le cose più recenti che hai scritto, è abbastanza semplice: corruzione della memoria. La corruzione della memoria può fare cose molto casuali. Questo probabilmente è uno di quelli :-)

+1

Stessa cosa per me ... –

+0

Nel mio progetto è sempre così (sbagliato), ma quando creo un nuovo progetto che funziona come previsto – user1269009

+0

@ user1269009 Quindi hai preso le due linee che ho scritto, copiato, incollato nel vostro VERBATIM vecchio progetto e guardato le zecche? – xanatos

Problemi correlati