אופרטורי ביטים#

האופרטורים הבוליאניים המיושמים על כל זוג ביטים במקביל, בתוספת שני ההיסטים. מספר שלם בן 32 או 64 ביט הוא, מנקודת מבטם של אופרטורים אלה, ווקטור של ערכים בלתי־תלויים בני ביט אחד.

אופרטור

פעולה

כלל לכל ביט

&

AND ביטי

כל ביט פלט = a b

|

OR ביטי

כל ביט פלט = a b

^

XOR ביטי

כל ביט פלט = a b

~

NOT ביטי

כל ביט פלט = ¬a (אונרי)

<<

היסט שמאלה

היסט ביטים שמאלה, מילוי באפסים מימין

>>

היסט ימינה

היסט ביטים ימינה

האופרנדים נכפים למספרים שלמים (עיגול כלפי אפס, עם אזהרות אם מסופקת מחרוזת שאינה שלמה תחת use warnings).

0xFF & 0x0F           # 0x0F     -- mask to low nibble
0x10 | 0x01           # 0x11     -- combine flag bits
0xFF ^ 0xAA           # 0x55     -- toggle alternating bits
~0                    # -1 (or all-ones, depending on integer width)
1  << 4               # 16
32 >> 2               # 8

קביעה, איפוס, החלפה ובדיקה של דגל#

ארבע פעולות הדגל הבסיסיות על ביט יחיד:

use constant FLAG_VERBOSE  => 0x01;
use constant FLAG_DRY_RUN  => 0x02;
use constant FLAG_RECURSE  => 0x04;
use constant FLAG_FORCE    => 0x08;

my $flags = 0;

$flags |=  FLAG_VERBOSE;       # SET    -- OR with the bit
$flags |=  FLAG_DRY_RUN;       # SET another
$flags &= ~FLAG_DRY_RUN;       # CLEAR  -- AND with the inverted bit
$flags ^=  FLAG_VERBOSE;       # TOGGLE -- XOR with the bit
my $on = $flags & FLAG_RECURSE;# TEST   -- AND, then test truthiness

כל אחד הוא יישום בן ביט אחד של אופרטור בוליאני: קביעה היא bit flag, איפוס הוא bit ¬flag, החלפה היא bit flag, בדיקה היא bit flag.

השמה מורכבת#

לכל ששת אופרטורי הביטים הבינאריים יש צורות מורכבות:

$bits  &= $mask;       # AND-assign
$flags |= 0x01;        # OR-assign  (set bit)
$x     ^= $y;          # XOR-assign (toggle bits where $y is 1)
$x   <<= 1;            # multiply-by-2 (with overflow caveats)
$x   >>= 1;            # divide-by-2 (toward -∞ for signed values)

היסטים#

<< מסיט שמאלה; >> מסיט ימינה. מספר עמדות הביטים להיסט הוא האופרנד הימני. היסט בכמות שלילית, או בכמות שווה או גדולה מרוחב הביטים של המספר השלם, מוגדר על־ידי המימוש - אל תסתמכו עליו.

עבור אריתמטיקה ללא סימן, היסט שמאלה הוא כפל ב־2 ** $n (מודולו גלישה):

$x << 1               # like $x * 2
$x << 8               # like $x * 256

עבור אריתמטיקה ללא סימן, היסט ימינה הוא חילוק שלם ב־2 ** $n:

$x >> 1               # like int($x / 2)   (for non-negative $x)
$x >> 8               # like int($x / 256)

עבור ערכים בעלי סימן, >> מוגדר על־ידי המימוש - Perl אינו מבטיח היסט אריתמטי לעומת לוגי. בצעו מסכה במפורש כשהסימן משנה:

($x >> 8) & 0xFF      # extract a byte at offset 8, regardless of sign

מצב מספרי לעומת מצב בית־אחר־בית#

אופרטורי הביטים של Perl פועלים על מספרים שלמים בברירת מחדל. עם use feature 'bitwise' (או use v5.22+), הצורות בעלות הסיומת &., |., ^., ~. פועלות על מחרוזות בית־אחר־בית:

use feature 'bitwise';
"\x80" |. "\x01"      # "\x81"  -- single-byte string OR
"abc"  ^. "abc"       # "\0\0\0" -- bytewise XOR

האופרטורים &, |, ^, ~ ללא קישוט תמיד מבצעים חשבון שלם, ואופרנדים מחרוזתיים נכפים למספרים תחילה. צורות ה־. בעלות הסיומת הן הדרך לבקש פעולות על מחרוזות־בתים במפורש.

החלפת XOR#

ל־XOR יש שתי תכונות - a a = 0 ו־a b b = a - שמשתלבות לכדי טריק ההחלפה־ללא־משתנה־עזר המפורסם:

my ($a, $b) = (0xFEED, 0xBEEF);

$a ^= $b;             # a := a ⊕ b
$b ^= $a;             # b := b ⊕ (a ⊕ b)  = a
$a ^= $b;             # a := (a ⊕ b) ⊕ a  = b

# $a == 0xBEEF, $b == 0xFEED

לא מהיר יותר מ־($a, $b) = ($b, $a) ב־Perl. כדאי להכיר משום שהוא מופיע בפולקלור של ראיונות ובקוד מוטמע, ומשום שהוא המחשה נקייה של זהות ה־XOR.

טריקי ביט נפוצים#

תבניות שתראו בקוד רגיש־ביצועים:

$x &  ($x - 1)            # $x with its lowest set bit cleared
($x & ($x - 1)) == 0      # true when $x is a power of two (and non-zero)
1 << $n                   # the integer with only bit $n set
$x & (1 << $n)            # is bit $n set in $x?
$x | (1 << $n)            # set bit $n
$x & ~(1 << $n)           # clear bit $n
$x ^ (1 << $n)            # toggle bit $n
($x >> $n) & 0xFF         # extract a byte at offset $n

כל אחת היא תרגיל במעקב אחר מה שכל ביט עושה - הסקה בוליאנית טהורה המיושמת 32 (או 64) פעמים במקביל.

הפניה צולבת להדרכה#

הדרכת הלוגיקה הבוליאנית כוללת טיפול ארוך יותר במודל הביטים־כבוליאני־מקבילי ובתבניות היישום שלעיל:

ראו גם#

  • לוגיקה - אותם אופרטורים בוליאניים על ערכים שלמים.

  • קדימות - &, |, ^ יושבים בין השוואה לבין &&/||. כמעט תמיד הקיפו אותם בסוגריים.

  • pack, unpack, vec - כלי perlfunc לעבודה ברמת הביטים מעבר למה שהאופרטורים הגולמיים מציעים.