سؤال

منذ datetime.adddays () يأخذ double المعلمة، أنا قلق من أنه عند إضافة أيام، قد يكون هناك بعض أخطاء التقريب. على سبيل المثال دعنا نقول أن لدي حلقة التالية:

DateTime Now = DateTime.Today;
for (int i = 0; i < 365; ++i)
{
    Now = Now.AddDays(1);
    // do something
}

أنا قلق من أن الآن قد تبدأ في الانجراف بعيدا عن منتصف الليل. أنا دائما إغراء أن أفعل شيئا مثل هذا قد يكون أبطأ قليلا، لكنه يخفف جنون العظمة:

for (int i = 0; i < 365; ++i)
{
    Now = Now.AddDays(1.01).Date;
    // do something
}
هل كانت مفيدة؟

المحلول

كما DateTime يخزن تاريخ Internaly كعدد صحيح 64 بت حيث يمثل علامة واحدة 100 Nanoseconds، لا يوجد خطر خطأ. يوم واحد لديه 864،000،000،000 القراد و Double لديه دقة لا تقل عن 15 رقما. لذلك اختفت كل خطأ عند التقريب إلى القراد Double لديه دقة أعلى من علامة واحدة إذا 1.0 يساوي يوم واحد.

هذا لن يكون صحيحا AddYears(), ، لأن Double ليس له دقة كافية لتمثيل علامة واحدة إذا 1.0 يساوي سنة واحدة. ولكن إذا نظرت إلى DateTime فئة، ترى أن التصميم يحترم هذه الحقيقة - AddMonths() و AddYears() كلاهما عدد صحيح وليس حجج النقطة العائمة.

للتحقق من هذا فقط تنفيذ التعليمات البرمجية التالية.

DateTime now = DateTime.Now;

// Displays 864000000000 
Console.WriteLine(now.AddDays(1.0).Ticks - now.Ticks);

نصائح أخرى

بشكل عام، أعتقد أنك صحيحا للقلق بشأن التقريب مع الزوجي لأنها ليست كل الأرقام الحقيقية عبارة عن تعبيرية تماما مع مثيل مزدوج، إذا كنت تضيف 1/3 من يوم ثلاث مرات، فقد لا ينتهي بك الأمر بالضبط تقدم يوم واحد. ومع ذلك، في هذه الحالة، 1 هو رقم غير قابل للتعبير تماما وكما تقوم ببساطة بضربه برقم آخر غير قابل للتعبير تماما في ضعف عدد القراد في يوم واحد)، يجب أن تكون على ما يرام. العينة الثانية ربما تكون مبالغة.

مثال:

DateTime now = DateTime.Today;
for (int i = 0; i < 7; ++i )
{
    for (int j = 0; j < 7; ++j )
    {
         now = now.AddDays( 1 / 7.0 );
    }
}
Console.WriteLine( DateTime.Today);
Console.WriteLine( now );

النتائج في (في 4/20/2009)

4/20/2009 12:00:00 AM
4/26/2009 11:59:59 PM

يضاعف عدد الأيام عددا صحيحا (المقياس) ثم يضاف إلى عدد القراد المخزنة من قبل DateTime. وبعد عند تمرير عدد صحيح، فسوف ينتهي الأمر بإضافة عدد صحيح من القراد.

من ناحية أخرى، لا أعرف ما الذي يقوم به .NET حول Leap Secks ... أظن أنه يستخدم نموذجا بسيطا جدا لا يهتم معهم، مما يترك الشفرة بخير.

لا تنس أن إضافة المناطق الزمنية تضيف مضاعفات إضافية - قد تضيف إضافة يوم محلي أكثر من يوم أو أقل من يوم من حيث UTC، والعكس بالعكس.

ماذا تقصد عن طريق الانجراف بعيدا عن منتصف الليل؟

عند تشغيل، يحتوي الرمز الأول على آخر تاريخ بعد 4/20/2010 12:00:00 صباحا.
أعتقد أن هذا هو ما تتوقعه. أليس كذلك؟

كما هو الحال في مثالك، أضفت يوم واحد إلى متغير تاريخي 100،000 مرة وما زالت انتهت تاريخا مع قيمة وقت منتصف الليل. يبدو أنه لا يوجد سبب للقلق.

أنا متأكد من أنهم يقضون إلى القراد الزمني، مما يلغي أي مشاكل مع الانجراف.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top