كيف يمكنني مقارنة بين يتوق كما الموقعة في جافا ؟

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

  •  05-07-2019
  •  | 
  •  

سؤال

أنا تخزين أنماط بت من غير موقعة 64 بت الأرقام في long متغير ترغب في حساب المسافة بين اثنين منهم على غير مجموعة.لأن جافا يفسر long كما المتمم صحيح وقعت, لا أستطيع a - b, كما يوضح المثال التالي:

// on the unsigned range, these numbers would be adjacent
long a = 0x7fffffffffffffffL;
long b = 0x8000000000000000L;

// but as two's complement (or any representation that 
// stores the sign in the first bit), they aren't
assert b - a == 1;

ما هي الطريقة الصحيحة للقيام بذلك ؟

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

المحلول

إذا كنت تتعامل مع الجمع والطرح، فإنه لا يهم ما إذا كنت تستخدم أنواع قعت أو غير الموقعة، طالما أن الحجج على حد سواء وقعت أو كليهما غير موقعة. إذا كنت في حاجة إلى المقارنة أ و ب، مقارنة ب-0.

نصائح أخرى

كما الحسابي يلتف جولة الأمور على نفس الحالة كنت تعطي.إذا كنت تفسير النتيجة غير موقعة القيمة ، وسوف يكون صحيحا في جميع الحالات أنت فقط تغيير تفسير نمط بت, انها لا تزال مجموعة متماثل الشكل إلى Ζ264.

ويعمل بالنسبة لي:

long a = 0x7fffffffffffffffL;
long b = 0x8000000000000000L;
b - a = (long) 1
a - b = (long) -1

ولقد استخدمت هذا الحل:

if (longA == longB) return 0;
return (longA < longB) ^ (longA < 0) ^ (longB< 0) ? 1 : -1;

جميع الاعتمادات تذهب إلى هذا الموقع

وبدءا على جافا 8 ، أو المقارنة بين long أنها أعداد صحيحة غير موقعة يمكن أن يتم عن طريق <لأ href = "https://docs.oracle.com/javase/8/docs/api/java /lang/Long.html#compareUnsigned-long-long- "يختلط =" نوفولو noreferrer "> Long.compareUnsigned (س، ص) .

وهنا هو backport بسيط لجافا 7 و في وقت سابق:

public static int compareUnsigned(long x, long y) {
   return Long.compare(x + Long.MIN_VALUE, y + Long.MIN_VALUE);
}

كما ذكر سابقا, لن يكون لديك مشكلة مع الطرح ، حتى إذا كان هذا هو كل ما كنت تحاول القيام به ، ثم لا تقلق.

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

الحلول:1.استخدام BigInteger بدلا من الطويلة. BigInteger تم إنشاء الحسابات مع أعداد كبيرة ويمكن بسهولة دعم 128bit العمليات الحسابية.

  1. الكتابة الخاصة بك العلائقية عمليات استبعاد استخدام إضافة أو الضرب احتمال ممكن.الكتابة الخاصة بك مشغل العلائقية هو حقا ليس من الصعب أن.أولا مقارنة بت الأكثر أهمية.إن الشيء الأكثر أهمية هو نفسه لكل الأرقام يمكن أن تخفي ذلك عن طريق القيام and (&) مع 0X7FFFFFFFFFFFFFFF ثم قارن بين ملثمين القيم.

ويمكنني استخدام التعليمات البرمجية التالية:

static boolean unsignedLessThan(long left, long right) { 
    return (left < right) ^ (left < 0) ^ (right < 0);
}

و(هذه البيانات تعتمد على سبيل المثال عن طريق Tamutnefret)

من الواضح أنك بحاجة الى اتفاق مع بت.

static boolean compare(long a, long b)
{
    if(( a &  (Long.MAX_VALUE + 1)) != 0)
        return ( b & (Long.MAX_VALUE + 1) )  != 0
            ? (a < b) //same sign 
            : true; //a is greater b
    else 
        return ( b & (Long.MAX_VALUE + 1) )  != 0
            ? false //b is greater a
            : a < b; //same sign
}

وأو يمكنك القيام نصف ونصف من هذا القبيل،

public static long unsignedDiff(long a, long b) {
    long mask = 0xFFFFFFFFL;
    return (( ((a >> 32) & mask) - ((b >> 32) & mask) ) << 32) +
       + ((a & mask) - (b & mask));
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top