Frage

Was ich will:

assert_equal 6, ones_complement(9)   # 1001 => 0110
assert_equal 0, ones_complement(15)  # 1111 => 0000
assert_equal 2, ones_complement(1)   # 01 => 10

Die Größe des Eingangs wird, wie in 4 Bits oder 8 Bits nicht festgelegt. vielmehr ist es ein Binärstroms.

Was ich sehe:

v = "1001".to_i(2)                 => 9

Es ist ein bisschen Flipping Operator ~

(~v).to_s(2)                       => "-1010"
sprintf("%b", ~v)                  => "..10110"
~v                                 => -10

Ich denke, das hat etwas mit einem Bit zu tun verwendet wird, um die Zeichen oder etwas zu speichern ... kann jemand diese Ausgabe erklären? Wie erhalte ich ein Einerkomplement, ohne wie in String-Manipulationen zurückgreifen, die letzten n Zeichen aus der sprintf Ausgabe Schneiden „0110“ oder ersetzen 0 mit 1 und umgekehrt

zu bekommen
War es hilfreich?

Lösung

Es klingt wie Sie nur vier Bits spiegeln möchten (die Länge Ihrer Eingabe) - so möchten Sie wahrscheinlich mit 1111 bis XOR

.

Andere Tipps

Rubin speichert nur eine (signiert) Nummer. Die interne Darstellung dieser Zahl ist nicht relevant: es könnte sonst ein Fixnum, BigNum oder so etwas. Daher ist die Anzahl der Bits in einer Reihe auch nicht definiert: es schließlich nur eine Zahl ist. Dies steht im Gegensatz zu beispielsweise C, wo ein int wahrscheinlich 32 Bit (fest) sein.

Was bedeutet der Operator ~ dann tun? Wel, nur so etwas wie:

class Numeric
    def ~
        return -self - 1
    end
end

... denn das ist, was ‚~‘ darstellt, wenn bei 2-Komplement-Zahlen suchen.

Also, was aus Ihrer Eingabe Aussage fehlt, ist die Anzahl von Bits, die Sie wechseln möchten: a. 32-Bit ~ unterscheidet sich von einem allgemeinen ~ wie es ist in Ruby

Nun, wenn Sie wollen einfach nur Bit-Flip-n-Bits, die Sie etwas tun können, wie:

class Numeric
    def ones_complement(bits)
        self ^ ((1 << bits) - 1)
    end
end

... aber Sie haben die Anzahl der Bits zu spezifizieren zu kippen. Und das wird nicht das Zeichen Flagge beeinflussen, da, dass man außerhalb Ihrer Reichweite mit XOR ist:)

Siehe diese Frage warum.

Ein Problem mit Ihrer Methode ist, dass Ihre erwartete Antwort nur wahr, wenn Sie nur die vier Bits kippen. 1001 -> 0110

Aber die Zahl mit führenden Nullen gespeichert, und der Operator ~ Flips alle führenden Bits zu: 00001001 -> 11110110. Dann wird die führende 1 als negatives Vorzeichen interpretiert.

Sie müssen wirklich angeben, was die Funktion sollte mit Zahlen wie 0b101 und 0b11011 tun, bevor Sie entscheiden können, wie es zu implementieren. Wenn Sie immer nur 4 Bits kippen möchten, können Sie v^0b1111, wie in eine andere Antwort vorgeschlagen. Aber wenn Sie alle Bits spiegeln möchten, wird es komplizierter.

Bearbeiten

Hier ist ein Weg, um alle Bits zu kippen:

def maskbits n
  b=1
  prev=n;
  mask=prev|(prev>>1)
  while (mask!=prev)
    prev=mask;
    mask|=(mask>>(b*=2))
  end
  mask
end

def ones_complement n
  n^maskbits(n)
end

Das gibt

p ones_complement(9).to_s(2)  #>>"110" 
p ones_complement(15).to_s(2) #>>"0"
p ones_complement(1).to_s(2)  #>>"0"

Dies ist nicht die gewünschte Ausgabe für ones_compliment (1) erhalten, weil es 1 als „1“ nicht „01“ behandelt. Ich weiß nicht, wie die Funktion könnte folgern, wie viele führende Nullen Sie wollen, ohne die Breite als Argument zu nehmen.

Was Sie tun, Operator (die ~ verwendet wird), ist in der Tat ein Einerkomplement. Sie sind diese Werte erhalten, die Sie wegen der Art und Weise nicht erwartet werden die Zahl von Ruby interpretiert wird.

Was Sie brauchen, um tatsächlich hängt zu tun, was Sie diese verwenden für. Das heißt, warum brauchen Sie ein 1-Komplement?

Wenn Sie Arbeit mit Strings sind Sie tun können:

s = "0110"
s.gsub("\d") {|bit| bit=="1"?"0":"1"}

:

Wenn Sie mit Zahlen arbeiten, werden Sie die Anzahl der Bits, weil definieren müssen 0110 = 6; 1001 = 9;
110 = 6; 001 = 1;

Auch das Zeichen zu ignorieren, werden Sie wahrscheinlich zu handhaben sind.

Beachten Sie, dass Sie den Einerkomplement jetzt mit ~ bekommen, wenn Sie in einer Fixnum passieren: die Anzahl der Bits, die die Zahl ist eine feste Größe im Interpreter darstellen und somit gibt es führenden 0en vor der Binärdarstellung die Nummer 9 (binär 1001). Sie können diese Anzahl von Bits finden, indem die Größe jeder Fixnum zu untersuchen. (Die Antwort wird in Bytes zurückgegeben)

1.size            #=> 4
2147483647.size   #=> 4

~ ist auch über Bignum definiert. In diesem Fall verhält sich, als ob alle Bits, die in der Bignum angegeben wurden umgedreht, und dann, wenn es eine unendliche Folge von 1en vor diesem Bignum waren. Sie können, schieben denkbar Ihre Bitstrom in eine Bignum und das Ganze umkehren. Sie müssen jedoch die Größe des Bitstrom wissen, vor der Inversion ein brauchbares Ergebnis zu erhalten, nachdem es invertiert wird.

Um die Frage zu beantworten, wie Sie es rechts von der Fledermaus darstellen, können Sie die größte Leistung von 2 weniger als der Eingang finden, verdoppeln, 1 subtrahiert, dann XOR das Ergebnis, dass mit Ihrer Eingabe und immer einen bekommt Einerkomplement nur die Bits in der Eingangsnummer.

def sig_ones_complement(num)
  significant_bits = num.to_s(2).length
  next_smallest_pow_2 = 2**(significant_bits-1)
  xor_mask = (2*next_smallest_pow_2)-1
  return num ^ xor_mask
end
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top