En forme masquée pour toute plate-forme (32 bits, 64 bits ... l'avenir aussi longtemps que PHP_INT_MAX
est définie) qui peut offrir un avantage de performance (pas de branchement):
function uintRShift($uint,$shift)
{
//if ($shift===0) return $uint;
//PHP_INT_MAX on 32 =7FFFFFFF, or zero & 32 ones
$mask=PHP_INT_MAX>>($shift-1);
return $uint>>$shift&$mask;
}
La puts configuration du masque tous les zéros pour les $shift
bits les plus à gauche de $uint
. Note: Décommenter la première ligne si vous voulez pouvoir/tolérer le décalage d'un nombre négatif/grand (puisque le masque modifiera un nombre négatif/grand même avec $shift=0
).
Le code de test unitaire pour montrer qu'il fonctionne en 32 bits:
class UintRShiftTest extends PHPUnit_Framework_TestCase {
public function provide_shifts() {
return array(
/* start shift end*/
array(0, 4, 0)
,array(0xf, 4, 0)
,array(0xff, 4, 0xf)
,array(0xfffffff, 4, 0xffffff)
,array(0xffffffff, 4, 0xfffffff)
,array(-1, 4, 0xfffffff)//Same as above
,array(0, 1, 0)
,array(0xf, 1, 0x7)
,array(-1, 1, 0x7fffffff)
);
}
/**
* @dataProvider provide_shifts
*/
function test_uintRShift($start,$shift,$end) {
$this->assertEquals($end,uintRShift($start,$shift));
}
}
Pour ce que ça vaut la fonction mentionnée ci-dessus:
function uintRShift_branch($uint,$shift)
{
if ($uint<0) {
return ($uint>>$shift)+(2<<~$shift);
} else {
return $uint>>$shift;
}
}
ne réussit pas le test automatisé:
# 4 Rapports -1
.Cela peut peut-être justifiée par PHP rapports 0xffffffff
comme un grand nombre positif (documentation suggère de grands entiers sont automagiquement passés à flotteurs, bien que le décalage de bits semble le traiter comme un entier régulier encore)
# 8 Résultats en -2147483649
qui est en fait correcte (comme 0x7fffffff
) mais au-dessous de la valeur int minimum pour PHP: -2147483648
donc ce que je dois faire fonction privée shiftRight3 ($ a, $ b) { si (is_n umeric ($ a) && $ a <0) { return $ a >> $ b + (2 << ~ $ b); } else { return $ a >> $ b; } } – shay
@shay: Oui, exactement. – Gumbo
merci à tous :) – shay