أبسط طريقة للتحقق مما إذا كان هناك عددان صحيحان لهما نفس الإشارة؟

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

  •  09-06-2019
  •  | 
  •  

سؤال

ما هي أبسط طريقة للتحقق مما إذا كان هناك عددان صحيحان لهما نفس الإشارة؟هل هناك أي خدعة bitwise قصيرة للقيام بذلك؟

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

المحلول

إليك إصدار يعمل في C/C++ ولا يعتمد على أحجام الأعداد الصحيحة أو لديه مشكلة التجاوز (أي.x*y>=0 لا يعمل)

bool SameSign(int x, int y)
{
    return (x >= 0) ^ (y < 0);
}

بالطبع، يمكنك الاطلاع على القالب والقالب:

template <typename valueType>
bool SameSign(typename valueType x, typename valueType y)
{
    return (x >= 0) ^ (y < 0);
}

ملحوظة:نظرًا لأننا نستخدم حصريًا أو، فإننا نريد أن يكون LHS وRHS مختلفين عندما تكون الإشارات متماثلة، وبالتالي يكون التحقق مختلفًا مقابل الصفر.

نصائح أخرى

ما المشكلة في

return ((x<0) == (y<0));  

?

(a ^ b) >= 0

سيتم تقييمه إلى 1 إذا كانت الإشارة هي نفسها، و0 بخلاف ذلك.

سأكون حذرًا من أي حيل لتحديد البتات لتحديد علامة الأعداد الصحيحة، حيث يتعين عليك بعد ذلك وضع افتراضات حول كيفية تمثيل هذه الأرقام داخليًا.

سيتم تخزين الأعداد الصحيحة في 100% تقريبًا من الوقت مجاملة اثنين, ، ولكن ليس من الممارسات الجيدة وضع افتراضات حول الأجزاء الداخلية للنظام إلا إذا كنت تستخدم نوع بيانات يضمن تنسيق تخزين معين.

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

أنا شخصياً سأستخدم وظيفة الإشارة للغة التي اخترتها.ومن غير المرجح أن يكون هناك أي مشاكل في الأداء مع عملية حسابية كهذه.

بافتراض 32 بت int:

bool same = ((x ^ y) >> 31) != 1;

أكثر إيجازًا قليلاً:

bool same = !((x ^ y) >> 31);

لست متأكدًا حقًا من أنني سأعتبر "خدعة البت" و"الأبسط" مترادفين.أرى الكثير من الإجابات التي تفترض أعدادًا صحيحة 32 بت موقعة (على الرغم من ذلك كان كن سخيفًا أن تطلب غير موقع)؛لست متأكدًا من أنها تنطبق على قيم الفاصلة العائمة.

يبدو أن الفحص "الأبسط" سيكون مقارنة كيفية مقارنة القيمتين بالصفر؛هذا عام جدًا بافتراض أنه يمكن مقارنة الأنواع:

bool compare(T left, T right)
{
    return (left < 0) == (right < 0);
}

إذا كانت العلامات معاكسة، فستحصل على خطأ.إذا كانت العلامات هي نفسها، تصبح صحيحا.

(عدد صحيح1 * عدد صحيح2) > 0

لأنه عندما يشترك عددان صحيحان في الإشارة، فإن نتيجة الضرب ستكون دائمًا موجبة.

يمكنك أيضًا جعلها >= 0 إذا كنت تريد التعامل مع 0 على أنه نفس العلامة مهما كان الأمر.

بافتراض أن الثنائيات مكملة للحساب (http://en.wikipedia.org/wiki/Two_complement):

inline bool same_sign(int x, int y) {
    return (x^y) >= 0;
}

يمكن أن يستغرق ذلك ما يصل إلى تعليمتين وأقل من 1 نانو ثانية على معالج حديث مع التحسين.

لا نفترض أن الثنائيات مكملة للحساب:

inline bool same_sign(int x, int y) {
    return (x<0) == (y<0);
}

قد يتطلب هذا تعليمات إضافية واحدة أو اثنتين ويستغرق وقتًا أطول قليلاً.

يعد استخدام الضرب فكرة سيئة لأنه عرضة للتجاوز.

إذا (س * ص) > 0...

بافتراض عدم الصفر ونحو ذلك.

كملاحظة فنية، ستكون الحلول المبتذلة أكثر كفاءة من الضرب، حتى في البنى الحديثة.إنها مجرد 3 دورات تقوم بحفظها، لكنك تعرف ما يقولون عن "توفير قرش"...

قبالة أعلى رأسي...

int mask = 1 << 31;
(a & mask) ^ (b & mask) < 0;

نسخة C بدون فروع:

int sameSign(int a, int b) {
    return ~(a^b) & (1<<(sizeof(int)*8-1));
}

قالب C++ لأنواع الأعداد الصحيحة:

template <typename T> T sameSign(T a, T b) {
    return ~(a^b) & (1<<(sizeof(T)*8-1));
}

لأي حجم من int مع حسابين مكملين:

#define SIGNBIT (~((unsigned int)-1 >> 1))
if ((x & SIGNBIT) == (y & SIGNBIT))
    // signs are the same

على افتراض 32 بت

if(((x^y) & 0x80000000) == 0)

...الاجابة if(x*y>0) سيئة بسبب الفائض

إذا كانت علامة (a*b < 0) مختلفة، فإن الإشارة الأخرى هي نفسها (أو تكون a أو b صفرًا)

بالعودة إلى أيام دراستي الجامعية، في معظم تمثيلات الآلات، أليس الجزء الموجود في أقصى اليسار من عدد صحيح هو 1 عندما يكون الرقم سالبًا، و0 عندما يكون موجبًا؟

أتصور أن هذا يعتمد إلى حد ما على الآلة.

int Same_sign =!( (x >> 31) ^ (y >> 31) );

إذا (نفس_العلامة) ...آخر ...

طريقة استخدام أفضل الأمراض المنقولة جنسيا::signbit على النحو التالي:

std::signbit(firstNumber) == std::signbit(secondNumber);

كما أنه يدعم الأنواع الأساسية الأخرى (double, float, char إلخ).

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