2012-03-14 33 views
12

Następne 2 wiersze dodają tę samą kwotę do tej samej daty, a część daty wyników jest taka sama, ale jakoś tam jest różnica w części czasu!Wydanie .NET Adddays

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

dostaniesz różnicę 15 sekund, a oba są z co najmniej roundable do dni, nie wiem, dlaczego tak się stało, ale to się zdarza tylko z AddDays, ale nie AddMonths (nawet z tysiącami miesięcy dodawanych)


Edycja 1

Więc próbowałem zrobić przykładowy projekt, ale bez powodzenia. Jeśli uruchomię mój główny projekt i wstawię przykładowe linie do zegarków, niż otrzymam 2 oddzielne wartości, jeśli zrobię nowy początek, problem nie istnieje. Projekt to 3.5, C#, vs2010, win7hp x64 (proj: x86). Próbuję odtworzyć to także w świeżym małym projekcie, odpiszę, jeśli go otrzymam.

Są to moje wyniki w głównym projektu (copeid od zegarków!):

(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 

Edycja 2

udało mi się sprowadzić jeszcze więcej. Posiadamy własny komponent, podstawę panelu, czerpimy z niego directx. Jeśli sprawię, że visible = false, than visible = true, wtedy błąd pojawi się przed visible = true (lub show()), obliczenia są poprawne. Co na świecie może tam być, że wynik dostaje coś innego od formuły, w której nie użyto żadnej zmiennej. Kultura nie jest naruszona w składniku ..

+0

może być problemem ze względu na typ danych, ponieważ AddDays wykonuje podwójne. Wydaje się jednak, że różnica powinna wynosić znacznie mniej niż 15 sekund. Sprawdź http://en.wikipedia.org/wiki/Double_precision, aby zobaczyć, jak to tylko przybliża wartości. –

+1

Czy próbowałeś odwrócenie kolejności metody wymaga, aby zobaczyć, jeśli uzyska ten sam wynik? Prawdopodobnie nie zrobi to różnicy, ale jestem ciekawy. –

+3

I nie były w stanie odtworzyć ten (na kompilator C# 4). Jakie jest twoje środowisko? – SWeko

Odpowiedz

3

Jest to wynik DirectX zmieniający cicho tryb obliczeń zmiennoprzecinkowych procesora, aby zawsze używać pojedynczej precyzji. Czasem dzieje się tak w przypadku wydajności: użycie pojedynczej precyzji może być nieco szybsze niż przy użyciu podwójnej precyzji. Zobacz opis flagi FpuPreserve w dokumentacji MSDN dla wyliczenia DirectX CreateFlags.

Powód, dla którego inni nie mogą tego odtworzyć, jest spowodowany tym, że nie wykonują tych połączeń DirectX.

Argumentem dla AddDays jest double. Ta wartość jest mnożona przez współczynnik skali, aby uzyskać czas w milisekundach. To właśnie to obliczenie powoduje błąd.

Rozważmy:

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); 

Wyrażenie milliseconds2 zawiera obsadę do float, który naśladuje działanie DirectX zmuszając obliczeń pojedynczej precyzji. To wydrukuje 15360, dokładnie taką, jaką znajdziesz.

Natomiast AddMonths bierze całkowitą, a nie korzysta z żadnej arytmetyki zmiennoprzecinkowej. Wynik jest dokładny.

4

Tu dają ten sam rezultat:

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; 

d2 d1 == == 634743432000000000

(kleszcz jest wewnętrzny "kwantowy" od chwili DateTime. jest to dość krótki. To one ten-millionth of a second

dodam, że nawet mono (niezależna implementacja .NET) daje ten sam wynik http://ideone.com/krySY (Ideone wykorzystuje mono)

Biorąc pod uwagę nowsze rzeczy, które napisałeś, jest to całkiem proste: uszkodzenie pamięci. Uszkodzenie pamięci może wykonywać bardzo przypadkowe rzeczy. Jest to prawdopodobnie jeden z następujących :-)

+1

To samo dla mnie ... –

+0

W moim projekcie zawsze tak jest (źle), ale kiedy tworzę nowy projekt działa on zgodnie z oczekiwaniami – user1269009

+0

@ user1269009 Więc wziąłeś dwie linie, które napisałem, skopiowałem wklejono to VERBATIM w twoje stary projekt i obserwował tyknięcia? – xanatos