سؤال

أنا أكتب خوارزميات تعمل على سلسلة من البيانات الرقمية، حيث في بعض الأحيان، يجب أن تكون القيمة في السلسلة فارغة.ومع ذلك، نظرًا لأن هذا التطبيق مهم للأداء، فقد تجنبت استخدام الأنواع الخالية.لقد قمت باختبار الخوارزميات لمقارنة أداء استخدام الأنواع الفارغة مقابل الأنواع غير الفارغة، وفي أفضل الأحوال تكون الأنواع الفارغة أبطأ بمقدار 2x، ولكنها غالبًا ما تكون أسوأ بكثير.

نوع البيانات الأكثر استخدامًا هو مزدوج، والبديل المختار حاليًا لـ null هو double.NaN.ومع ذلك، فأنا أفهم أن هذا ليس الاستخدام الدقيق المقصود لقيمة NaN، لذلك لست متأكدًا مما إذا كانت هناك أية مشكلات في هذا لا يمكنني توقعها وما هي أفضل الممارسات.

أنا مهتم بمعرفة أفضل البدائل الخالية لأنواع البيانات التالية على وجه الخصوص:double/float، decimal، DateTime، int/long (على الرغم من أن الآخرين مرحب بهم للغاية)

يحرر:أعتقد أنني بحاجة إلى توضيح متطلباتي بشأن الأداء.تتم معالجة عدد كبير من البيانات الرقمية من خلال هذه الخوارزميات في وقت يستغرق عدة ساعات.لذلك، على الرغم من أن الفرق بين 10 مللي ثانية أو 20 مللي ثانية على سبيل المثال يكون عادةً غير مهم، إلا أنه في هذا السيناريو يكون له تأثير كبير على الوقت المستغرق.

هل كانت مفيدة؟

المحلول

حسنا، إذا كنت قد استبعدت Nullable<T>, ، تبقى لديك قيم المجال - على سبيل المثال.رقم سحري تعامله على أنه فارغ.في حين أن هذا ليس كذلك مثالي, ، إنه ليس من غير المألوف أيضًا - على سبيل المثال، الكثير من التعامل مع كود إطار العمل الرئيسي DateTime.MinValue نفس فارغة.وهذا على الأقل يبعد الضرر عن القيم المشتركة...

تحرير لتسليط الضوء فقط حيث لا يوجد NaN

إذن حيث لا يوجد NaN, ، ربما استخدم .MinValue - ولكن تذكر فقط ما يحدث من شرور إذا حدث ذلك عن طريق الخطأ يستخدم نفس القيمة تعني نفس العدد...

من الواضح أنك ستحتاج إلى البيانات غير الموقعة .MaxValue (تجنب الصفر!!!).

شخصيا، سأحاول استخدام Nullable<T> للتعبير عن نيتي بشكل أكثر أمانًا ...قد تكون هناك طرق لتحسين Nullable<T> رمز، ربما.وأيضًا - بحلول الوقت الذي تتحقق فيه من الرقم السحري في جميع الأماكن التي تحتاج إليها، ربما لن يكون أسرع بكثير من Nullable<T>?

نصائح أخرى

وأنا إلى حد ما نختلف مع Gravell على هذه الحالة حافة محددة: يعتبر "غير معرف" متغير خالية إد، فإنه لا يكون لها قيمة. وبغض النظر عن يستخدم للإشارة إلى أن ما يرام: حتى الأرقام السحرية، ولكن مع الأرقام السحرية عليك أن تأخذ في الاعتبار أن الرقم السحري سوف تطارد دائما لكم في المستقبل عندما تصبح قيمة 'صالح' فجأة. مع Double.NaN لم يكن لديك لتخافوا لذلك: انها لن تصبح مزدوجة صالح. رغم ذلك، عليك أن تنظر التي نان بمعنى تسلسل الزوجي يمكن استخدامها فقط كعلامة ل"غير معرف"، لا يمكنك استخدامه بمثابة رمز خطأ في تسلسل كذلك، ومن الواضح.

وهكذا كل ما يستخدم في تحديد "غير معروف": يجب أن يكون واضحا في سياق مجموعة من القيم التي أن قيمة محددة تعتبر قيمة "غير معروف" وهذا لن يتغير في المستقبل.

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

أنا أعمل على مشروع كبير يستخدم NaN كملف null قيمة.أنا لست مرتاحًا تمامًا لذلك - لأسباب مماثلة لأسبابك:عدم معرفة ما يمكن أن يحدث خطأ.لم نواجه أي مشاكل حقيقية حتى الآن، ولكن انتبه إلى ما يلي:

حسابيات نان - على الرغم من أن "الترويج لـ NaN" يعد أمرًا جيدًا في معظم الأحيان، إلا أنه قد لا يكون دائمًا ما تتوقعه.

مقارنة - تصبح مقارنة القيم مكلفة إلى حد ما، إذا كنت تريد مقارنة القيم المتساوية بـ NaN.الآن، اختبار العوامات من أجل المساواة ليس بالأمر السهل على أي حال، ولكن الترتيب (a < b) يمكن أن يصبح قبيحًا حقًا، لأن قيمة nan تحتاج أحيانًا إلى أن تكون أصغر، وأحيانًا أكبر من القيم العادية.

عدوى الكود - أرى الكثير من التعليمات البرمجية الحسابية التي تتطلب معالجة محددة لـ NaN لتكون صحيحة.لذلك ينتهي بك الأمر إلى "الوظائف التي تقبل NaN" و"الوظائف التي لا تقبل" لأسباب تتعلق بالأداء.

أخرى غير نهائية NaN هي القيمة الوحيدة غير المحدودة.وينبغي أن يوضع في الاعتبار...

استثناءات النقطة العائمة ليست مشكلة عند تعطيلها.حتى يمكّنهم أحد.قصة حقيقية:التهيئة الثابتة لـ NaN في عنصر تحكم ActiveX.لا يبدو الأمر مخيفًا، حتى تقوم بتغيير التثبيت لاستخدام InnoSetup، الذي يستخدم نواة Pascal/Delphi(؟)، والتي تم تمكين استثناءات FPU فيها افتراضيًا.استغرق مني بعض الوقت لمعرفة ذلك.

لذا، بشكل عام، لا يوجد شيء خطير، على الرغم من أنني أفضل عدم الاضطرار إلى التفكير في NaNs كثيرًا.


سأستخدم الأنواع Nullable كلما أمكن ذلك، ما لم تكن (ثبت أنها) قيود على الأداء/الموارد.يمكن أن تكون إحدى الحالات عبارة عن ناقلات/مصفوفات كبيرة تحتوي على NaNs عرضية، أو مجموعات كبيرة من القيم الفردية المسماة حيث يكون سلوك NaN الافتراضي صحيحًا.


وبدلاً من ذلك، يمكنك استخدام متجه فهرس للمتجهات والمصفوفات، أو تطبيقات "المصفوفة المتفرقة" القياسية، أو متجه منطقي/بت منفصل.

والإجابة الجزئية:

وتعويم ومزدوجة توفر نان (ليس عدد). نان هو صعب قليلا منذ ذلك الحين، في المواصفات، نان! = نان. إذا كنت ترغب في معرفة ما إذا كان العدد هو نان، سوف تحتاج إلى استخدام Double.IsNaN ().

وانظر أيضا ثنائي النقطة العائمة و. NET .

وربما انخفاض أداء هامة يحدث عند استدعاء أحد أعضاء قيم الفارغة أو خصائص (الملاكمة).

وحاول استخدام البنية مع ضعف + منطقي قول ما اذا كان يتم تحديد قيمة أم لا.

ويمكن للمرء تجنب بعض تدهور الأداء المرتبطة Nullable<T> من خلال تحديد الهيكل الخاص بك

struct MaybeValid<T>
{
    public bool isValue;
    public T Value;
}

إذا رغبت في ذلك، يمكن للمرء أن يحدد منشئ، أو عامل تحويل من T إلى MaybeValid<T>، وما إلى ذلك ولكن الإفراط في استخدام مثل هذه الأمور قد تسفر عن أداء دون المستوى الأمثل. يمكن البنيات حقل مكشوف تكون فعالة إذا كان أحد يتجنب نسخ البيانات غير الضرورية. بعض الناس قد التجهم على فكرة الحقول المكشوفة، ولكنها يمكن أن تكون أكثر كفاءة واسع أن خصائص. إذا وظيفة التي سيعود T أن الحاجة إلى وجود متغير من نوع T لعقد قيمة عودتها، وذلك باستخدام MaybeValid<Foo> ببساطة يزيد بنسبة 4 حجم شيء يمكن إرجاعها. على النقيض من ذلك، فإن استخدام Nullable<Foo> تتطلب وظيفة أولا حساب Foo ثم تمر على نسخة منه إلى منشئ لNullable<Foo>. وعلاوة على ذلك، والعودة إلى Nullable<Foo> سيتطلب أن أي قانون يريد استخدام القيمة التي تم إرجاعها يجب جعل نسخة واحدة على الأقل إضافية إلى موقع التخزين (متغير أو مؤقت) من نوع Foo قبل أن تتمكن من فعل أي شيء مفيد معها. على النقيض من ذلك، يمكن استخدام كود مجال Value متغير من نوع Foo حول بكفاءة كما أي متغير آخر.

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