declare(strict_types=1);
/**
* Returns the zero-based position of the most significant set bit (MSB)
* in an unsigned integer.
*
* Examples:
* 1 -> 0
* 2 -> 1
* 8 -> 3
* 15 -> 3
*
* @param int $value Unsigned integer value to examine.
*
* @return int
* Zero-based position of the highest set bit.
* Returns -1 if $value is 0.
*/
function getMsbPosition(int $value): int
{
if ($value < 0) {
throw new InvalidArgumentException(
'Value must be a non-negative integer.'
);
}
if ($value === 0) {
return -1;
}
$position = 0;
while ($value > 1) {
$value >>= 1;
$position++;
}
return $position;
}
/*
* Example usage.
*/
$testValues = [
0,
1,
2,
8,
15,
0x1234,
2147483648
];
foreach ($testValues as $value) {
$position = getMsbPosition($value);
if ($position >= 0) {
echo sprintf(
"Value: %u, MSB position: %d\n",
$value,
$position
);
} else {
echo sprintf(
"Value: %u, no bits are set\n",
$value
);
}
}
/*
run:
Value: 0, no bits are set
Value: 1, MSB position: 0
Value: 2, MSB position: 1
Value: 8, MSB position: 3
Value: 15, MSB position: 3
Value: 4660, MSB position: 12
Value: 2147483648, MSB position: 31
*/