Erstes Set finden - Find first set

In Computer - Software und Hardware, finden ersten Satz ( FFS ) oder Finden der erste Eins a Bitoperation , dass ein unsigned gegebenes Maschinenwort , um den Index oder die Position des niedrigstwertigen Bit auf einen in der Wortzählung von dem niedrigstwertigen Bit bezeichnet Position. Eine nahezu äquivalente Operation ist das Zählen von nachgestellten Nullen ( ctz ) oder die Anzahl von nachgestellten Nullen ( ntz ), die die Anzahl von Null-Bits zählt, die dem niederwertigsten Bit folgen. Die komplementäre Operation, die den Index oder die Position des höchstwertigen gesetzten Bits findet, ist die logarithmische Basis 2 , so genannt, weil sie den binären Logarithmus ⌊log 2 (x)⌋ berechnet . Dies steht in engem Zusammenhang mit der Zählung führender Nullen ( clz ) oder der Anzahl der führenden Nullen ( nlz ), die die Anzahl der Nullbits vor dem höchstwertigen Bit zählt. Es gibt zwei gängige Varianten von Find First Set, die POSIX- Definition, die die Indizierung von Bits bei 1 beginnt, hier als ffs bezeichnet, und die Variante, die die Indizierung von Bits bei Null beginnt, die äquivalent zu ctz ist und daher mit diesem Namen bezeichnet wird.

Die meisten modernen CPU- Befehlssatzarchitekturen bieten einen oder mehrere davon als Hardwareoperatoren; Softwareemulation wird normalerweise für alle bereitgestellt, die nicht verfügbar sind, entweder als intrinsische Compiler oder in Systembibliotheken.

Beispiele

Gegeben das folgende 32-Bit-Wort:

0000 0000 0000 0000 1000 0000 0000 1000

Die Operation zum Zählen der abschließenden Nullen würde 3 zurückgeben, während die Operation zum Zählen der führenden Nullen 16 zurückgibt. Die Zählung der führenden Nullen hängt von der Wortgröße ab: Wenn dieses 32-Bit-Wort auf ein 16-Bit-Wort gekürzt würde, würde die Zählung der führenden Nullen Null zurückgeben . Die Operation Find first set würde 4 zurückgeben, was die vierte Position von rechts anzeigt. Die Logbasis 2 ist 15.

In ähnlicher Weise gilt für das folgende 32-Bit-Wort die bitweise Negation des obigen Wortes:

1111 1111 1111 1111 0111 1111 1111 0111

Die Operation zum Zählen der nachfolgenden Einsen würde 3 zurückgeben, die Operation zum Zählen der führenden Einsen würde 16 zurückgeben und die Operation zum Finden der ersten Null ffz würde 4 zurückgeben.

Wenn das Wort null ist (keine Bits gesetzt), geben führende Nullen zählen und nachfolgende Nullen zählen beide die Anzahl der Bits im Wort zurück, während ffs null zurückgibt. Sowohl log-Basis-2- als auch nullbasierte Implementierungen von find first set geben im Allgemeinen ein undefiniertes Ergebnis für das Null-Wort zurück.

Hardware-Unterstützung

Viele Architekturen enthalten Anweisungen zum schnellen Durchführen von Find-First-Set- und/oder verwandten Operationen, die unten aufgelistet sind. Die gebräuchlichste Operation ist das Zählen führender Nullen (clz), wahrscheinlich weil alle anderen Operationen in Bezug darauf effizient implementiert werden können (siehe Eigenschaften und Beziehungen ).

Plattform Gedächtnisstütze Name Operandenbreiten Beschreibung Auf Antrag auf 0
ARM ( ARMv5T-Architektur und höher )
außer Cortex-M0/M0+/M1/M23
clz Führende Nullen zählen 32 clz 32
ARM ( ARMv8-A-Architektur ) clz Führende Nullen zählen 32, 64 clz Operandenbreite
AVR32 clz Führende Nullen zählen 32 clz 32
DEZ Alpha ctlz Führende Nullen zählen 64 clz 64
cttz Nachgestellte Nullen zählen 64 ctz 64
Intel 80386 und höher bsf Bit-Scan vorwärts 16, 32, 64 ctz Nicht definiert; setzt Null-Flag
bsr Bit-Scan-Umkehrung 16, 32, 64 Stammbasis 2 Nicht definiert; setzt Null-Flag
x86 unterstützt BMI1 oder ABM lzcnt Führende Nullen zählen 16, 32, 64 clz Operandenbreite; setzt Carry Flag
x86 unterstützt BMI1 tzcnt Nachgestellte Nullen zählen 16, 32, 64 ctz Operandenbreite; setzt Carry Flag
Itanium clz Führende Nullen zählen 64 clz 64
MIPS clz Führende Nullen in Word zählen 32, 64 clz Operandenbreite
schließen Zählen Sie die führenden in Word 32, 64 schließen Operandenbreite
Motorola 68020 und höher bfffo Erstes im Bitfeld finden Willkürlich Stammbasis 2 Feldoffset + Feldbreite
PDP-10 jffo Springen Sie, wenn Sie den ersten finden 36 ctz 0; keine Operation
POWER / PowerPC / Power ISA cntlz/cntlzw/cntlzd Führende Nullen zählen 32, 64 clz Operandenbreite
Power ISA 3.0 und höher cnttzw/cnttzd Nachgestellte Nullen zählen 32, 64 ctz Operandenbreite
RISC-V ("B"-Erweiterung) (Entwurf) clz Führende Nullen zählen 32, 64 clz Operandenbreite
ctz Nachgestellte Nullen zählen 32, 64 ctz Operandenbreite
SPARC Oracle Architecture 2011 und höher lzcnt (Synonym: lzd) Führende Nullzählung 64 clz 64
Mehrwertsteuer ffs Erstes Set finden 0–32 ctz Operandenbreite; setzt Null-Flag
IBM z/Architektur flogr Ganz links finden 64 clz 64
vclz Vektorzählung führender Nullen 8, 16, 32, 64 clz Operandenbreite
vctz Vektorzählung nachgestellte Nullen 8, 16, 32, 64 ctz Operandenbreite

Auf einigen Alpha-Plattformen werden CTLZ und CTTZ in Software emuliert.

Tool- und Bibliotheksunterstützung

Eine Reihe von Compiler- und Bibliotheksanbietern bieten Compiler-Intrinsic- oder Bibliotheksfunktionen an, um Find-First-Set- und/oder verwandte Operationen durchzuführen, die häufig in Bezug auf die obigen Hardware-Anweisungen implementiert werden:

Werkzeug/Bibliothek Name Typ Eingabetyp(en) Anmerkungen Auf Antrag auf 0
POSIX .1 konforme libc
4.3BSD libc
OS X 10.3 libc
ffs Bibliotheksfunktion int Enthält glibc . POSIX liefert nicht die ergänzende Logbase 2 / clz. 0
FreeBSD 5.3 libc
OS X 10.4 libc
ffsl
fls
flsl
Bibliotheksfunktion int,
lang
fls("finde letzte Menge") berechnet (Log-Basis 2) + 1. 0
FreeBSD 7.1 libc ffsll
flsll
Bibliotheksfunktion lang Lang 0
GCC 3.4.0
Clang 5.x
__builtin_ffs[l,ll,imax]
__builtin_clz[l,ll,imax]
__builtin_ctz[l,ll,imax]
Eingebaute Funktionen unsigned int,
unsigned long,
unsigned long long,
uintmax_t
Die GCC-Dokumentation betrachtet das Ergebnis undefiniert clz und ctz auf 0. 0 (ffs)
Visual Studio 2005 _BitScanForward
_BitScanReverse
Compiler-Eigenschaften unsigned long,
unsigned __int64
Separater Rückgabewert zur Anzeige von Nulleingaben Nicht definiert
Visual Studio 2008 __lzcnt Compiler-intrinsisch unsigned short,
unsigned int,
unsigned __int64
Setzt auf Hardwareunterstützung für den lzcnt-Befehl, der in BMI1 oder ABM eingeführt wurde . Operandenbreite
Intel C++-Compiler _bit_scan_forward
_bit_scan_reverse
Compiler-Eigenschaften int Nicht definiert
NVIDIA CUDA __clz Funktionen 32-Bit, 64-Bit Kompiliert mit weniger Anweisungen auf der GeForce 400-Serie 32
__ffs 0
LLVM llvm.ctlz.*
llvm.cttz.*
Intrinsisch 8, 16, 32, 64, 256 LLVM-Assemblersprache Operandenbreite, wenn 2. Argument 0 ist; undefiniert sonst
GHC 7.10 (Basis 4.8), ZollData.Bits countLeadingZeros
countTrailingZeros
Bibliotheksfunktion FiniteBits b => b Haskell-Programmiersprache Operandenbreite
C++20- Standardbibliothek, im Header<bit> bit_ceil bit_floor
bit_width
countl_zero countl_one
countr_zero countr_one
Bibliotheksfunktion unsigned char,
unsigned short,
unsigned int,
unsigned long,
unsigned long long

Eigenschaften und Beziehungen

Wenn Bits beginnend bei 1 beschriftet sind (was die in diesem Artikel verwendete Konvention ist), dann zählen nachfolgende Nullen und die Operationen zum Suchen des ersten Satzes sind durch ctz( x ) = ffs( x ) − 1 verbunden (außer wenn die Eingabe null ist). Wenn Bits beginnend bei 0 beschriftet sind , dann zählen nachfolgende Nullen und Find First Set sind genau äquivalente Operationen. Bei w Bits pro Wort lässt sich log 2 leicht aus clz berechnen und umgekehrt durch log 2 ( x ) = w − 1 − clz ( x ) .

Wie im obigen Beispiel gezeigt, können die Operationen Erste Null finden, führende Einsen zählen und nachfolgende Einsen zählen implementiert werden, indem die Eingabe negiert und erster Satz gefunden, führende Nullen zählen und nachfolgende Nullen zählen verwendet werden. Das Umgekehrte gilt auch.

Auf Plattformen mit einem effizienten Log- 2- Betrieb wie M68000 kann ctz wie folgt berechnet werden:

ctz( x ) = log 2 ( x & −x )

wo & Bezeichnet bitweise UND und -x bezeichnet das Zweier - Komplement von x . Der Ausdruck x & −x löscht alle außer dem niederwertigsten 1 Bit, sodass das höchstwertige und das niedrigstwertige 1 Bit gleich sind.

Auf Plattformen mit einer effizienten Operation zum Zählen führender Nullen wie ARM und PowerPC kann ffs wie folgt berechnet werden:

ffs( x ) = w −clz( x & −x ) .

Im Gegensatz dazu auf Maschinen ohne log 2 oder clz Operatoren clz berechnet werden unter Verwendung von ctz , wenn auch ineffizient:

CIZ = w - CTZ (2 ⌈log 2 ( x ) ⌉ ) (die davon abhängt , CTZ zurückkehr w für den Null - Eingang)

Auf Plattformen mit einem effizienten Hamming - Gewicht (Bevölkerungszahl) Betrieb wie SPARC ‚s POPCoder Blackfin ‘ s ONESgibt es:

ctz( x ) = popcount(( x & −x ) − 1) , oder ctz( x ) = popcount(~( x | −x )) ,
ffs( x ) = Popcount( x ^ ~− x )
clz = 32 − popcount(2 ⌈log 2 ( x )⌉ − 1)

wobei ^ bitweises Exklusiv-ODER bezeichnet, | bezeichnet bitweises ODER und ~ bezeichnet bitweise Negation.

Das umgekehrte Problem (bei i , erzeugt eine x , so daß CTZ ( x ) = i ) mit einer Linksverschiebung (berechnet wird 1 << i ).

Find first set und verwandte Operationen können auf einfache Weise auf beliebig große Bit-Arrays erweitert werden, indem an einem Ende begonnen und bis zu einem Wort fortgefahren wird , das nicht ganz null (für ffs , ctz , clz ) oder nicht ganz eins (für ffz .) ist , clo , cto ) gefunden wird. Eine Baumdatenstruktur, die rekursiv Bitmaps verwendet, um zu verfolgen, welche Wörter ungleich Null sind, kann dies beschleunigen.

Softwareemulation

Die meisten CPUs aus den späten 1980er Jahren haben Bitoperatoren für ffs oder gleichwertig, einige moderne CPUs wie einige der ARM-Mx-Serien jedoch nicht. Anstelle von Hardware-Operatoren für ffs, clz und ctz kann Software diese mit Verschiebungen, Integer-Arithmetik und bitweisen Operatoren emulieren. Es gibt verschiedene Ansätze, die von der Architektur der CPU und in geringerem Maße von der Programmiersprachensemantik und der Qualität der Compilercodegenerierung abhängen. Die Ansätze können lose beschrieben werden als lineare Suche , binäre Suche , Suche + Tabellensuche, de Bruijn-Multiplikation, Gleitkomma-Umwandlung/Exponenten-Extraktion und Bitoperator-(verzweigungslose) Verfahren. Es gibt Kompromisse zwischen Ausführungszeit und Speicherplatz sowie Portabilität und Effizienz.

Softwareemulationen sind normalerweise deterministisch. Sie geben für alle Eingabewerte ein definiertes Ergebnis zurück; insbesondere ist das Ergebnis für eine Eingabe aller Nullbits normalerweise 0 für ffs und die Bitlänge des Operanden für die anderen Operationen.

Wenn man eine Hardware-Clz oder ein Äquivalent hat, kann ctz effizient mit Bitoperationen berechnet werden, aber das Gegenteil ist nicht der Fall: clz ist ohne einen Hardware-Operator nicht effizient zu berechnen.

2 n

Die Funktion 2 ⌈log 2 (x)⌉ ( aufgerundet auf die nächste Zweierpotenz) mit Verschiebungen und bitweisen ODERs ist nicht effizient zu berechnen wie in diesem 32-Bit-Beispiel und noch ineffizienter, wenn wir eine 64-Bit- oder 128-Bit-Funktion haben -Bit-Operand:

function pow2(x):
    if x = 0 return invalid  // invalid is implementation defined (not in [0,63])
    x ← x - 1
    for each y in {1, 2, 4, 8, 16}: x ← x | (x >> y)
    return x + 1

FFS

Da ffs = ctz + 1 (POSIX) oder ffs = ctz (andere Implementierungen) sind, können die anwendbaren Algorithmen für ctz verwendet werden, mit einem möglichen letzten Schritt des Addierens von 1 zum Ergebnis und der Rückgabe von 0 anstelle der Operandenlänge für die Eingabe von alle Nullbits.

CTZ

Der kanonische Algorithmus ist eine Schleife, die Nullen beginnend beim LSB zählt, bis ein 1-Bit angetroffen wird:

function ctz1 (x)
    if x = 0 return w
    t ← 1
    r ← 0
    while (x & t) = 0
        t ← t << 1
        r ← r + 1
    return r

Dieser Algorithmus führt O(n) Zeit und Operationen aus und ist in der Praxis aufgrund einer großen Anzahl von bedingten Verzweigungen unpraktisch.

Eine Nachschlagetabelle kann die meisten Verzweigungen eliminieren:

table[0..2n-1] = ctz(i) for i in 0..2n-1
function ctz2 (x)
    if x = 0 return w
    r ← 0
    loop
        if (x & (2n-1)) ≠ 0
            return r + table[x & (2n-1)]
        x ← x >> n
        r ← r + n

Der Parameter n ist fest (normalerweise 8) und repräsentiert einen Zeit-Raum-Kompromiss . Die Schlaufe kann auch vollständig ausgerollt werden . Aber als lineares Nachschlagen ist dieser Ansatz immer noch O(n) in der Anzahl der Bits im Operanden.

Eine binäre Suchimplementierung erfordert eine logarithmische Anzahl von Operationen und Verzweigungen, wie in dieser 32-Bit-Version: Dieser Algorithmus kann auch durch eine Tabelle unterstützt werden, indem die unteren drei "if"-Anweisungen durch eine Lookup-Tabelle mit 256 Einträgen ersetzt werden, die das erste nicht -null Byte als Index gefunden.

function ctz3 (x)
    if x = 0 return 32
    n ← 0
    if (x & 0x0000FFFF) = 0: n ← n + 16, x ← x >> 16
    if (x & 0x000000FF) = 0: n ← n +  8, x ← x >>  8
    if (x & 0x0000000F) = 0: n ← n +  4, x ← x >>  4
    if (x & 0x00000003) = 0: n ← n +  2, x ← x >>  2
    if (x & 0x00000001) = 0: n ← n +  1
    return n

Wenn die Hardware einen clz-Operator hat, ist der effizienteste Ansatz zur Berechnung von ctz daher:

function ctz4 (x)
    x &= -x
    return w - (clz(x) + 1)

Ein Algorithmus für 32-Bit-ctz verwendet de Bruijn-Sequenzen , um eine minimale perfekte Hash-Funktion zu konstruieren , die alle Verzweigungen eliminiert. Dieser Algorithmus geht davon aus, dass das Ergebnis der Multiplikation auf 32 Bit gekürzt wird.

for i from 0 to 31: table[ ( 0x077CB531 * ( 1 << i ) ) >> 27 ] ← i  // table [0..31] initialized
function ctz5 (x)
    return table[((x & -x) * 0x077CB531) >> 27]

Der Ausdruck (x & -x) isoliert wiederum das niederwertigste 1 Bit. Es gibt dann nur noch 32 mögliche Wörter, die durch die vorzeichenlose Multiplikation und Shift an die richtige Position in der Tabelle gehasht werden. (Dieser Algorithmus verarbeitet die Nulleingabe nicht.)

CLZ

Der kanonische Algorithmus untersucht ein Bit nach dem anderen, beginnend mit dem MSB, bis ein Nicht-Null-Bit gefunden wird, wie in diesem Beispiel gezeigt. Er wird in O(n)-Zeit ausgeführt, wobei n die Bitlänge des Operanden ist und kein praktischer Algorithmus für den allgemeinen Gebrauch ist.

function clz1 (x)
    if x = 0 return w
    t ← 1 << (w - 1)
    r ← 0
    while (x & t) = 0
        t ← t >> 1
        r ← r + 1
    return r

Eine Verbesserung gegenüber dem vorherigen Schleifenansatz untersucht acht Bits gleichzeitig und verwendet dann eine Nachschlagetabelle mit 256 (2 8 ) Einträgen für das erste Byte ungleich Null. Dieser Ansatz ist jedoch immer noch O(n) in der Ausführungszeit.

function clz2 (x)
    if x = 0 return w
    t ← 0xff << (w - 8)
    r ← 0
    while (x & t) = 0
        t ← t >> 8
        r ← r + 8
    return r + table[x >> (w - 8 - r)]

Die binäre Suche kann die Ausführungszeit auf O(log 2 n) reduzieren :

function clz3 (x)
    if x = 0 return 32
    n ← 0
    if (x & 0xFFFF0000) = 0: n ← n + 16, x ← x << 16
    if (x & 0xFF000000) = 0: n ← n +  8, x ← x <<  8
    if (x & 0xF0000000) = 0: n ← n +  4, x ← x <<  4
    if (x & 0xC0000000) = 0: n ← n +  2, x ← x <<  2
    if (x & 0x80000000) = 0: n ← n +  1
    return n

Die schnellsten portablen Ansätze zur Simulation von clz sind eine Kombination aus binärer Suche und Tabellensuche: Eine 8-Bit-Tabellensuche (2 8 = 256 1-Byte-Einträge) kann die unteren 3 Zweige der binären Suche ersetzen. 64-Bit-Operanden erfordern einen zusätzlichen Zweig. Ein Lookup mit größerer Breite kann verwendet werden, aber die maximale praktische Tabellengröße wird durch die Größe des L1-Datencaches auf modernen Prozessoren begrenzt, die für viele 32 KB beträgt. Das Speichern einer Verzweigung wird durch die Latenzzeit eines L1-Cache- Fehltreffers mehr als ausgeglichen .

Ein Algorithmus ähnlich der de Bruijn-Multiplikation für CTZ funktioniert für CLZ, aber anstatt das höchstwertige Bit zu isolieren, rundet er mithilfe von Verschiebungen und bitweisen ODERs auf die nächste ganze Zahl der Form 2 n −1 auf:

table[0..31] = {0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
                8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31}
function clz4 (x)
    for each y in {1, 2, 4, 8, 16}: x ← x | (x >> y)
    return table[((x * 0x07C4ACDD) >> 27) % 32]

Bei Prozessoren mit tiefen Pipelines, wie Prescott und späteren Intel-Prozessoren, kann es schneller sein, Verzweigungen durch bitweise AND- und ODER-Operatoren zu ersetzen (auch wenn viel mehr Anweisungen erforderlich sind), um Pipeline-Flushes für falsch vorhergesagte Verzweigungen zu vermeiden (und diese Arten von Verzweigungen sind von Natur aus .) unvorhersehbar):

function clz5 (x)
   r = (x > 0xFFFF) << 4; x >>= r;
   q = (x > 0xFF  ) << 3; x >>= q; r |= q;
   q = (x > 0xF   ) << 2; x >>= q; r |= q;
   q = (x > 0x3   ) << 1; x >>= q; r |= q;
                                   r |= (x >> 1);
   return r;

Auf Plattformen, die eine Hardwarekonvertierung von ganzen Zahlen in Gleitkommazahlen bereitstellen, kann das Exponentenfeld extrahiert und von einer Konstanten subtrahiert werden, um die Anzahl der führenden Nullen zu berechnen. Korrekturen sind erforderlich, um Rundungsfehler zu berücksichtigen. Die Gleitkomma-Konvertierung kann eine beträchtliche Latenzzeit haben. Diese Methode ist in hohem Maße nicht tragbar und wird normalerweise nicht empfohlen.

int x; 
int r;
union { unsigned int u[2]; double d; } t; 

t.u[LE] = 0x43300000;  // LE is 1 for little-endian
t.u[!LE] = x;
t.d -= 4503599627370496.0;
r = (t.u[LE] >> 20) - 0x3FF;  // log2
r++;  // CLZ

Anwendungen

Die Operation zum Zählen führender Nullen (clz) kann verwendet werden, um eine Normalisierung effizient zu implementieren , die eine ganze Zahl als m  × 2 e codiert , wobei m sein höchstwertiges Bit an einer bekannten Position (wie der höchsten Position) hat. Dies kann wiederum verwendet werden, um eine Newton-Raphson-Division zu implementieren , eine Ganzzahl-zu- Gleitkomma- Umwandlung in Software durchzuführen und andere Anwendungen.

Zählen führender Nullen (clz) kann verwendet werden, um das 32-Bit-Prädikat "x = y" (null wenn wahr, eins wenn falsch) über die Identität clz(x − y) >> 5 zu berechnen , wobei ">>" vorzeichenlos ist rechte Shifttaste. Es kann verwendet werden, um komplexere Bitoperationen wie das Finden der ersten Folge von n 1 Bits durchzuführen . Der Ausdruck clz(x − y)1 << (16 − clz(x − 1)/2) ist eine effektive Anfangsschätzung für die Berechnung der Quadratwurzel einer 32-Bit-Ganzzahl unter Verwendung der Newton-Methode . CLZ effizient implementieren Nullunterdrückung , eine schnelle Datenkompressionstechnik , die eine ganze Zahl als die Anzahl von führenden Null - Bytes zusammen mit dem Nicht - Null - Bytes codiert. Es kann auch effizient exponentiell verteilte ganze Zahlen erzeugen, indem es die clz von gleichmäßig zufälligen ganzen Zahlen nimmt.

Die logarithmische Basis 2 kann verwendet werden, um zu antizipieren, ob eine Multiplikation überlaufen wird, da log 2 (xy)⌉ log 2 (x)⌉ + ⌈log 2 (y)⌉ .

Führende Nullen zählen und nachfolgende Nullen zählen können zusammen verwendet werden, um den Schleifenerkennungsalgorithmus von Gosper zu implementieren , der die Periode einer Funktion mit endlichem Bereich unter Verwendung begrenzter Ressourcen finden kann.

Der binäre GCD-Algorithmus verbringt viele Zyklen damit, nachfolgende Nullen zu entfernen; dies kann durch eine Zählung mit nachgestellten Nullen (ctz) gefolgt von einer Verschiebung ersetzt werden. Eine ähnliche Schleife tritt bei Berechnungen der Hagelkornfolge auf .

Ein Bit-Array kann verwendet werden, um eine Prioritätswarteschlange zu implementieren . In diesem Zusammenhang ist Find First Set (ffs) nützlich beim effizienten Implementieren der "Pop"- oder "Pull-Element mit der höchsten Priorität"-Operation. Zu diesem Zweck wird intern der Echtzeit-Scheduler des Linux-Kernels verwendet sched_find_first_bit().

Die Operation Count Trailing Zeros liefert eine einfache optimale Lösung für das Turm-von-Hanoi- Problem: Die Scheiben werden von Null aus nummeriert, und bei Bewegung k wird die Scheibennummer ctz( k ) um den kleinstmöglichen Abstand nach rechts verschoben (Rückkreisen um die links nach Bedarf). Er kann auch einen Gray-Code erzeugen , indem er ein beliebiges Wort nimmt und das Bit ctz( k ) in Schritt k umkehrt .

Siehe auch

Anmerkungen

Verweise

Weiterlesen

Externe Links