Gibt es einen wahnsinnigen Trick, um die Teilbarkeit einer Zahl um 2 oder 3 zu überprüfen?

Ich suche nach einem bitweisen Test gleich (num%2) == 0 || (num%3) == 0 (num%2) == 0 || (num%3) == 0 .

Ich kann num%2 mit num&1 ersetzen, aber ich bin immer noch mit num%3 und mit dem logisch-oder.

  • Bitweise Operationen in Python
  • Wie vertrete und arbeite ich mit n-Bit-Vektoren in Python?
  • Konvertieren Sie Zeilen von hexadezimalen Werten in binäre, vertikal nach Spalte
  • Unterschied zwischen ^ Operator in JS und Python
  • Konvertieren von Bits in Bytes in Python
  • Wie man ein bitwise NOR Gate in Python (Editing Python Mathe, um für mich zu arbeiten)
  • Dieser Ausdruck ist auch äquivalent zu (num%2)*(num%3) == 0 , aber ich bin mir nicht sicher, wie das hilft.

  • Python: Wie funktioniert die Vererbung von __slots__ in Unterklassen eigentlich?
  • Single Table Vererbung in Django
  • Welche Klassen können nicht untergeordnet werden?
  • Wie "perfekt" einen Dict überschreiben kann?
  • Python - Verwenden Sie pytest, um Testmethoden zu testen, die in Unterklasse geschrieben wurden
  • Python: Wie man eine Klasse mit einer anderen Basisklasse rebilt oder dynamisch ersetzt
  • 2 Solutions collect form web for “Gibt es einen wahnsinnigen Trick, um die Teilbarkeit einer Zahl um 2 oder 3 zu überprüfen?”

    Ja, obwohl es nicht sehr hübsch ist, kannst du etwas Ähnliches mit der alten "Summe aller Dezimalstellen machen, bis du nur einen links" trickst, um zu testen, ob eine Zahl durch 9 teilbar ist, außer in binärer und mit Teilbarkeit durch 3. du Kann das gleiche Prinzip für andere Zahlen auch verwenden, aber viele Kombinationen von base / divisor stellen lästige Skalierungsfaktoren vor, so dass du nicht nur Ziffern summierst.

    Wie auch immer, 16 n -1 ist durch 3 teilbar, so können Sie radix 16 verwenden, das heißt, Summe der Nibbles. Dann bist du mit einem knabbern (gut, 5 Bits wirklich), und du kannst einfach so aussehen. Also zum Beispiel in C # (leicht getestet) edit: brute-force getestet, definitiv funktioniert

     static bool IsMultipleOf3(uint x) { const uint lookuptable = 0x49249249; uint t = (x & 0x0F0F0F0F) + ((x & 0xF0F0F0F0) >> 4); t = (t & 0x00FF00FF) + ((t & 0xFF00FF00) >> 8); t = (t & 0x000000FF) + ((t & 0x00FF0000) >> 16); t = (t & 0xF) + ((t & 0xF0) >> 4); return ((lookuptable >> (int)t) & 1) != 0; } 

    Der Trick von meinem Kommentar, x * 0xaaaaaaab <= 0x55555555 , arbeitet durch einen modularen multiplikativen inversen Trick. 0xaaaaaaab * 3 = 1 mod 2 32 , was bedeutet, dass 0xaaaaaaab * x = x / 3 genau dann, wenn
    x % 3 = 0 . "If" weil 0xaaaaaaab * 3 * y = y (weil 1 * y = y ), also wenn x von der Form ist
    3 * y dann wird es zurück zu y . "Nur wenn", weil keine zwei Eingänge auf die gleiche Ausgabe abgebildet sind, so dass alles, was nicht durch 3 teilbar ist, auf etwas höher als das höchste, was man bekommen kann, indem man etwas durch 3 (das ist 0xFFFFFFFF / 3 = 0x55555555 ).

    Sie können mehr darüber lesen (einschließlich der allgemeineren Form, die eine Rotation beinhaltet) in der Division durch invariante Integer mit Multiplikation (T. Granlund und PL Montgomery) .

    Du Compiler kann diesen Trick nicht kennen. Zum Beispiel:

     uint32_t foo(uint32_t x) { return x % 3 == 0; } 

    Wird auf Clang 3.4.1 für x64,

     movl %edi, %eax movl $2863311531, %ecx # imm = 0xAAAAAAAB imulq %rax, %rcx shrq $33, %rcx leal (%rcx,%rcx,2), %eax cmpl %eax, %edi sete %al movzbl %al, %eax ret 

    G ++ 4,8:

     mov eax, edi mov edx, -1431655765 mul edx shr edx lea eax, [rdx+rdx*2] cmp edi, eax sete al movzx eax, al ret 

    Was sollte es sein:

     imul eax, edi, 0xaaaaaaab cmp eax, 0x55555555 setbe al movzx eax, al ret 

    Ich glaube, ich bin ein bisschen spät für diese Party, aber hier ist eine etwas schnellere (und etwas hübscher) Lösung als die von Harold:

     bool is_multiple_of_3(std::uint32_t i) { i = (i & 0x0000FFFF) + (i >> 16); i = (i & 0x00FF) + (i >> 8); i = (i & 0x0F) + (i >> 4); i = (i & 0x3) + (i >> 2); const std::uint32_t lookuptable = 0x49249249; return ((lookuptable >> i) & 1) != 0; } 

    Es ist C ++ 11, aber das ist nicht wirklich wichtig für dieses Stück Code. Es ist auch Brute-Force getestet für 32-Bit unsigned Ints. Es spart Ihnen mindestens ein Bit-Fiddling op für jeden der ersten vier Schritte. Es skaliert auch schön auf 64 Bits – nur ein zusätzlicher Schritt benötigt am Anfang.

    Die letzten beiden Zeilen sind offensichtlich und schamlos aus Harolds Lösung genommen (schön, das hätte ich nicht so elegant gemacht).

    Mögliche weitere optimierungen:

    • Die & ops in den ersten beiden Schritten werden weg optimiert, indem sie einfach die untergeordneten Register auf Architekturen verwenden, die sie haben (zB x86).
    • Die größtmögliche Ausgabe aus dem dritten Schritt ist 60 , und ab dem vierten Schritt ist es 15 (wenn das Funktionsargument 0xFFFFFFFF ). Angesichts der Tatsache, dass wir den vierten Schritt beseitigen können, verwenden Sie ein 64-Bit- lookuptable und verschieben Sie direkt in das nach dem dritten Schritt. Dies erweist sich als eine schlechte Idee für Visual C ++ 2013 im 32-Bit-Modus, da die richtige Verschiebung zu einem Nicht-Inline-Aufruf zum Code führt, der viele Tests und Sprünge macht. Allerdings sollte es eine gute Idee sein, wenn 64-Bit-Register nativ verfügbar sind.
    • Der Punkt oben muss neu bewertet werden, wenn die Funktion geändert wird, um ein 64-Bit-Argument zu nehmen. Die maximalen Ausgänge der letzten beiden Schritte (die Schritte 4 und 5 nach dem Hinzufügen eines Schrittes am Anfang) werden 75 und 21 , was bedeutet, dass wir den letzten Schritt nicht mehr beseitigen können.

    Die ersten vier Schritte basieren auf der Tatsache, dass eine 32-Bit-Zahl geschrieben werden kann als

     (high 16 bits) * 65536 + (low 16 bits) = (high 16 bits) * 65535 + (high 16 bits) + (low 16 bits) = (high 16 bits) * 21845 * 3 + ((high 16 bits) + (low 16 bits)) 

    So ist das Ganze nur dann durch 3 teilbar, wenn die rechte Klammer durch 3 teilbar ist. Und so weiter, wie dies für 256 = 85 * 3 + 1 , 16 = 5 * 3 + 1 und 4 = 3 + 1 . (Natürlich ist dies in der Regel für gerade Kräfte von zwei, seltsame Kräfte sind eine weniger als die nächste Vielfalt von 3.)

    Die Zahlen, die in die folgenden Schritte eingegeben werden, werden in einigen Fällen größer als 16-Bit, 8-Bit und 4-Bit sein, aber das ist kein Problem, da wir keine höherwertigen Bits beim Verschieben nach rechts fallen lassen .

    Python ist die beste Programmiersprache der Welt.