2012-03-14 27 views
12

Hai dòng tiếp theo thêm cùng một số tiền vào cùng một ngày và phần ngày kết quả giống nhau, nhưng bằng cách nào đó có sự khác biệt trong phần thời gian!Số phát hành .NET AddDays

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

bạn sẽ nhận được một sự khác biệt của 15 giây, và với cả hai đều ít nhất roundable đến ngày này, tôi không biết lý do tại sao việc này xảy ra, nhưng nó chỉ xảy ra với AddDays, nhưng không AddMonths (ngay cả với hàng ngàn tháng thêm)


Sửa 1

Vì vậy, tôi đã cố gắng để thực hiện một dự án mẫu, nhưng không có may mắn. Nếu tôi chạy dự án chính của tôi, và đặt các dòng mẫu vào đồng hồ, hơn tôi nhận được 2 giá trị riêng biệt, nếu tôi thực hiện một khởi đầu mới, vấn đề là không có. Dự án là 3,5, C#, vs2010, win7hp x64 (proj: x86). Tôi đang cố gắng để tái tạo nó cũng trong một dự án nhỏ tươi, tôi sẽ viết lại nếu tôi có nó.

Đây là kết quả của tôi trong dự án chính (copeid từ đồng hồ!):

(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 

Chỉnh sửa 2

tôi đã quản lý để thu hẹp nó xuống hơn nữa. Chúng tôi có một thành phần tự làm, bảng điều khiển cơ sở, chúng tôi vẽ trên nó với directx. Nếu tôi làm cho rằng có thể nhìn thấy = false, hơn hiển thị = true, so với lỗi đến, trước khi hiển thị = true (hoặc show()), phép tính là chính xác. Cái gì trên thế giới có thể ở đó, rằng kết quả nhận được cái gì đó khác của một công thức mà không có biến nào được sử dụng. Văn hóa không bị ảnh hưởng trong các thành phần ..

+0

Có thể là một vấn đề do datatype, vì AddDays mất gấp đôi. Có vẻ như sự khác biệt nên được ít hơn rất nhiều 15 giây, mặc dù. Xem http://en.wikipedia.org/wiki/Double_precision để xem nó chỉ xấp xỉ giá trị như thế nào. –

+1

Bạn đã thử đảo ngược thứ tự của các cuộc gọi phương thức để xem bạn có nhận được kết quả tương tự không? Nó có lẽ sẽ không tạo ra sự khác biệt nhưng tôi tò mò. –

+3

Tôi đã không thể tái tạo điều này (trên trình biên dịch C# 4). Môi trường của bạn là gì? – SWeko

Trả lời

3

Đây là kết quả của DirectX âm thầm thay đổi chế độ tính toán dấu phẩy động của CPU để luôn sử dụng độ chính xác đơn. Điều này đôi khi được thực hiện cho hiệu suất: sử dụng độ chính xác đơn có thể khá nhanh hơn một chút so với sử dụng độ chính xác gấp đôi. Xem mô tả về cờ FpuPreserve trong tài liệu MSDN để liệt kê DirectX CreateFlags.

Lý do khiến người khác không thể tái tạo điều này là do họ không thực hiện các cuộc gọi DirectX đó.

Đối số cho AddDaysdouble. Giá trị này được nhân với hệ số tỷ lệ để nhận thời gian tính bằng mili giây. Chính tính toán này tạo ra lỗi.

xem xét:

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

Khái niệm cho milliseconds2 chứa một dàn diễn viên để float, mà bắt chước tác dụng của DirectX buộc tính toán chính xác đơn. Điều này sẽ in 15360, chính xác sự khác biệt mà bạn tìm thấy.

Ngược lại, AddMonths lấy số nguyên và không sử dụng bất kỳ số học dấu phẩy động nào. Vì vậy, kết quả là chính xác.

4

Ở đây họ đưa ra kết quả tương tự:

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 == == 634743432000000000

(các Tick là "lượng tử" nội bộ của thời điểm DateTime. đó là khá ngắn. đó là one ten-millionth of a second

tôi sẽ thêm rằng ngay cả mono (một thực hiện độc lập với NET) cho kết quả tương tự http://ideone.com/krySY (Ideone sử dụng mono)

0.123.

Xem xét những điều gần đây bạn đã viết, nó khá dễ dàng: tham nhũng bộ nhớ. Tham nhũng bộ nhớ có thể làm những điều rất ngẫu nhiên. Đây có thể là một trong những :-)

+1

Điều tương tự cho tôi ... –

+0

Trong dự án của tôi, nó luôn luôn như thế (sai), nhưng khi tôi tạo một dự án mới, nó hoạt động như mong đợi – user1269009

+0

@ user1269009 Vì vậy, bạn đã lấy hai dòng tôi đã viết, sao chép-dán nó VERBATIM trong của bạn dự án cũ và theo dõi ve? – xanatos

Các vấn đề liên quan