هل هناك وقت جيد لاستخدام Int32 بدلا من Sint32 في مخازن بروتوكول Google؟

StackOverflow https://stackoverflow.com/questions/765916

  •  12-09-2019
  •  | 
  •  

سؤال

لقد كنت أقرأ مخازن بروتوكول جوجل في الآونة الأخيرة، والتي تسمح باستخدام مجموعة متنوعة من أنواع قيمة العددية في الرسائل.

وفق وثائقهم, ، هناك ثلاثة أنواع من البدائيات عدد صحيح طول المتغير - int32, uint32, ، و sint32. وبعد في وثائقهم، يلاحظون ذلك int32 هو "غير فعال لترميز الأرقام السلبية - إذا كان من المحتمل أن يكون حقلك قيما سلبية، فاستخدم sint32 بدلا من ذلك. "ولكن إذا كان لديك حقل لا يوجد لديه أرقام سلبية، أفترض أن UINT32 سيكون نوعا أفضل لاستخدامه من int32 على أي حال (بسبب القليل الإضافي وانخفاض تكلفة وحدة المعالجة المركزية لمعالجة الأرقام السلبية).

لذلك متى int32 يكون العددية جيدة لاستخدامها؟ هل تؤثر الوثائق على أنها أكثر كفاءة فقط عندما نادرا ما تحصل على أرقام سلبية؟ أو هل هو الأفضل دائما استخدام sint32 و uint32, ، اعتمادا على محتويات الحقل؟

(تنطبق نفس الأسئلة على إصدارات 64 بت من هذه العدادات كذلك: int64, uint64, ، و sint64; ؛ لكنني تركتهم من مشكلة وصف قابلية القراءة.)

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

المحلول

أنا لست على دراية ببروتوكول Google المخازن المؤقتة، ولكن التفسير الخاص بي للوثائق هو:

  • استعمال uint32 إذا كانت القيمة لا يمكن أن تكون سلبية
  • استعمال sint32 إذا كانت القيمة من المرجح أن تكون سلبية إلى حد كبير لا تكون (للحصول على بعض التعريف الغامض "على الأرجح")
  • استعمال int32 إذا كانت القيمة يمكن أن تكون سلبية، ولكن هذا أقل احتمالا بكثير من القيمة الإيجابية (على سبيل المثال، إذا كان التطبيق يستخدم أحيانا -1 للإشارة إلى وجود خطأ أو "غير معروف" وهذا موقف غير مألوف نسبيا)

إليك ما يجب أن يقول المستندات حول الترميزات (http:/code.google.com/apis/protocolbuffers/docs/encoding.html#types.):

هناك فرق مهم بين الأنواع الدولية الموقعة (sint32 و sint64) وأنواع "قياسية" الدولية (int32 و int64) عندما يتعلق الأمر بترميز الأرقام السالبة. كما ترى int32 أو int64 كنوع رقم سالب، الناتج varint هو دائما عشرة بايت طويلة - إنه، بفعالية، تعامل مثل عدد صحيح غير موقعة للغاية. إذا كنت تستخدم واحدة من الأنواع الموقع، والنتيجة varint يستخدم ترميز Zigzag، وهو أكثر كفاءة بكثير.

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

لذلك يبدو أنه حتى إذا كان استخدامك للأرقام السلبية نادرة، طالما أن حجم الأرقام (بما في ذلك الأرقام غير السالبة)، فأنت تمرير في البروتوكول موجود على الجانب الأصغر، فقد تكون أفضل حالا باستخدام sint32. وبعد إذا كنت غير متأكد، فستكون التنميط بالترتيب.

نصائح أخرى

هناك سبب وجيه للغاية للاستخدام على الإطلاق * بدلا من Sint *. من المرجح أن يكون وجود هذه الأنواع الإضافية لأسباب توافق تاريخية وخلفية، يحاول المخازن المؤقتة البروتوكول الحفاظ عليها حتى عبر إصدارات البروتوكول الخاصة بها.

أفضل تخميني هو أنه في أقرب إصدار قاموا بتشفير أعداد صحيحة من الأعداد الصحيحة السلبية في التمثيل المتكامل 2، والذي يتطلب ترميز Varint الحجم الحجم بحجم 9 بايت (وليس عد البايت من النوع الإضافي). ثم كانت عالقة مع تلك الترميز حتى لا تكسر التعليمات البرمجية القديمة والتسوقات التي استخدمتها بالفعل. لذلك، يحتاجون إلى إضافة نوع ترميز جديد، Sint *، للحصول على ترميز أفضل الحجم بشكل أفضل للأرقام السالبة أثناء عدم كسر التعليمات البرمجية الموجودة. كيف لم يدرك المصممون هذه المشكلة من الحصول على الذهاب تماما وراءي.

يمكن أن ترميز ترميز VARINT (بدون مواصفات نوع، والتي تتطلب 1 أكثر بايت) قيمة عدد صحيح غير موقعة في عدد البايتات التالية:

0، 2 ^ 7): بايت واحد

2 ^ 7، 2 ^ 14): اثنان بايت

2 ^ 14، 2 ^ 21): ثلاثة بايت

2 ^ 21، 2 ^ 28): أربعة بايت

2 ^ 28، 2 ^ 35): خمس بايت

2 ^ 35، 2 ^ 42): ستة بايت

2 ^ 42، 2 ^ 49): سبعة بايت

2 ^ 49، 2 ^ 56): ثمانية بايت

2 ^ 56، 2 ^ 64): تسعة بايت

إذا كنت ترغب في تشفير بشكل مشابه من الأعداد الصحيحة السلبية بالحجم الصغير مضغوط، فستحتاج إلى "استخدام" قليلا للإشارة إلى علامة. يمكنك القيام بذلك من خلال بتوقية واضحة (في بعض الموقف المحجوز) وتمثيل الحجم. أو يمكنك القيام بترميز ZIG ZAG، الذي يقوم بفعالية بنفس الشيء الذي يتراجع عن ارتفاع الحجم بنسبة 1 بت وطرح 1 للأرقام السالبة (بحيث يشير البتة الأقل أهمية إلى علامة: Evens غير سلبية، احتمالات سلبية).

في كلتا الحالتين، قطع النقاط التي إيجابي الأعداد الصحيحة تتطلب مساحة أكبر الآن تأتي الآن عاملا في وقت سابق:

0، 2 ^ 6): بايت واحد

2 ^ 6، 2 ^ 13): اثنان بايت

2 ^ 13، 2 ^ 20): ثلاثة بايت

2 ^ 20، 2 ^ 27): أربعة بايت

2 ^ 27، 2 ^ 34): خمس بايت

2 ^ 34، 2 ^ 41): ستة بايت

2 ^ 41، 2 ^ 48): سبعة بايت

2 ^ 48، 2 ^ 55): ثمانية بايت

2 ^ 55، 2 ^ 63): تسعة بايت

لجعل القضية لاستخدامها باستخدام INT * عبر Sint *، يجب أن تكون الأرقام السالبة نادرة للغاية، ولكنها ممكنة، و / أو القيم الإيجابية الأكثر شيوعا التي تتوقع أن ترميز سترتشفها سقطت حول واحدة من النقاط التي تؤدي إلى ترميز أكبر في Sint * بدلا من Int * (على سبيل المثال - 2 ^ 6 مقابل 2 ^ 7 يؤدي إلى حجم ترميز 2x).

في الأساس، إذا كنت ستحصل على أرقام حيث قد يكون البعض سالبا، فاستخدم افتراضيا Sint * بدلا من int *. Int * نادرا ما يكون متفوقا للغاية وعادة ما لن يستحق التفكير الإضافي الذي يجب أن تكرسه نحو الحكم على ما إذا كان الأمر يستحق كل هذا العناء أم لا IMHO.

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