Poměrně málo známou a často zcela opomíjenou schopností PHP jsou bitové operace. Ty slouží k manipulaci s čísly (a trochu netradičně také s řetězci) na úrovni jednotlivých bitů. Co jednotlivé operace představují zachycuje následující tabulka:
$a | $b | $a | $b | $a & $b | $a ^ $b | ~ $a |
---|---|---|---|---|---|
0 | 0 | 0 | 0 | 0 | 1 |
0 | 1 | 1 | 0 | 1 | 1 |
1 | 0 | 1 | 0 | 1 | 0 |
1 | 1 | 1 | 1 | 0 | 0 |
Operace se provádějí na vzájemně si odpovídajících bitech, takže např. 6 | 10 = 14 (binárně 0110 | 1010 = 1110).
V PHP se bitové operace používají nejčastěji při předávání parametrů funkcím a při nastavování konfiguračních direktiv v kombinaci s konstantami. Asi nejčastěji se používají u funkce a direktivy error_reporting. Pro sloučení více hodnot se někdy nesprávně používá operátor +, který se stejně jako | chová pouze v případě, že spojované hodnoty nemají nastavené stejné bity, navíc je o něco pomalejší.
Na uživatelské úrovni se v PHP pro předávání sady parametrů obvykle používá více proměnných nebo pole, ale i bitové operace mohou v některých případech stále dobře posloužit:
<?php define("OPTION_A", 1); define("OPTION_B", 2); define("OPTION_C", 4); define("OPTION_ALL", OPTION_A | OPTION_B | OPTION_C); function bit_options($options) { $return = ""; if ($options & OPTION_A) { $return .= "a"; } if ($options & OPTION_B) { $return .= "b"; } if ($options & OPTION_C) { $return .= "c"; } return $return; } echo bit_options(OPTION_ALL & ~OPTION_B) . "\n"; ?>
Bitové operace samozřejmě nejsou žádnou výsadou PHP, např. v MySQL je používám hlavně při práci se sloupci typu set, pro což se dá ovšem použít i funkce FIND_IN_SET.
Nejintenzivněji jsem bitové operátory v poslední době použil u alternativních cen hotelů. Jde o to, že hotel používá dvoje ceny pro různé dny v týdnu. Které dny to jsou, jsem si uložil do datového typu set('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat')
. Pro následné zjištění informace o tom, která cena se má použít, jsem vytvořil následující kód:
<?php $alternativni_ceny = mysql_result(mysql_query("SELECT 1*alternativni_ceny FROM hotely WHERE id = $id"), 0); $cena = ((1 << date("w")) & $alternativni_ceny ? $alternativni_cena : $cena); ?>
Konstrukce 1*alternativni_ceny
z datového typu set vytvoří číslo s bity nastavenými podle pořadí hodnot nastavených v množině. Operátor << je bitový posun, konstrukce 1 << date("w")
tedy vytvoří číslo s bitem nastaveným podle aktuálního dne v týdnu. Logický součin s dříve získanou hodnotou potom zjistí, zda den spadá do období alternativních nebo normálních cen.
Diskuse je zrušena z důvodu spamu.