Frage

Ich bin zu speichern Bitmuster unsigned 64-Bit-Zahlen in einer long variabel und will den Abstand zwischen zwei von ihnen auf dem unsignierten Bereich zu berechnen. Da Java long als ein Zweier-Komplement Ganzzahl mit Vorzeichen interpretiert, kann ich nicht nur a - b tun, wie das folgende Beispiel zeigt:

// 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;

Was ist der richtige Weg, dies zu tun?

War es hilfreich?

Lösung

Wenn Sie mit Addition und Subtraktion zu tun haben, ist es egal, ob Sie mit oder ohne Vorzeichen Typen, solange die Argumente sowohl signiert oder beides ohne Vorzeichen. Wenn Sie ein und b vergleichen müssen, vergleichen, a-b auf 0.

Andere Tipps

Wie die arithmetische Runde wickelt, funktioniert es das gleiche für den Fall aus dir geben. Wenn Sie das Ergebnis als Wert ohne Vorzeichen interpretieren, wird es für alle Fälle wahr sein - du bist nur die Interpretation des Bitmuster zu ändern, es ist immer noch eine Menge homomorphes auf Ζ 2 64 .

Funktioniert bei mir:

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

Ich habe diese Lösung:

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

Alle Gutschriften auf dieser Website gehen

Beginnend mit Java 8 , der Vergleich von long als ganze Zahlen ohne Vorzeichen a href getan werden kann, über <= "https://docs.oracle.com/javase/8/docs/api/java /lang/Long.html#compareUnsigned-long-long-“rel = "nofollow noreferrer"> Long.compareUnsigned (x, y) .

Hier ist eine einfache Rückportierung für Java 7 und früher:

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

Wie bereits erwähnt, werden Sie kein Problem mit Subtraktion haben, so dass, wenn alles, was Sie zu tun versuchen, dann mach dir keine Sorgen.

Aber durch Ihr Beispiel, zusätzlich überlaufen, und keiner der relationalen Operatoren ordnungsgemäß funktionieren. Wenn dies ein Problem ist, dann können Sie Ihre eigenen relationalen ops schreiben, oder einen besseren Boxtyp als Lang verwenden.

Lösungen: 1. Verwenden Sie BigInteger statt Long. BigInteger wurde tun Berechnungen mit großen erstellt Zahlen und 128-Bit-Berechnungen leicht unterstützen können.

  1. Ihre eigenen relationalen Operationen schreiben und die verwendete Addition oder Multiplikation als Möglichkeit auszuschließen. Ihren eigenen relationalen Operator zu schreiben ist wirklich nicht so schwer. Erstens vergleichen Sie die höchstwertigen Bits. Wenn das höchstwertige Bit das gleiche für beide Zahlen ist, können Sie es maskieren, indem eine bitweise tun und (&) mit 0X7FFFFFFFFFFFFFFF und dann die maskierten Werte vergleichen.

Ich verwende den folgenden Code:

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

(basierend auf Beispiel durch Tamutnefret)

Natürlich müssen Sie mit Bits befassen.

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
}

Sie können auch wie diese halb und halb tun,

public static long unsignedDiff(long a, long b) {
    long mask = 0xFFFFFFFFL;
    return (( ((a >> 32) & mask) - ((b >> 32) & mask) ) << 32) +
       + ((a & mask) - (b & mask));
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top