我试图以一种数字(在php中)将数字分解为例如:
我不知道正确的术语是什么,但我认为这个想法很明确。
我的循环解决方案非常简单:
$number = rand(0, 128);
$number_array_loop = array();
$temp_number = $number;
while ($temp_number > 0) {
$found_number = pow(2, floor(log($temp_number, 2)));
$temp_number -= $found_number;
$number_array_loop[] = $found_number;
}
我也有一个递归的解决方案,但我不能在不使用全局变量的情况下工作(不想这样),以下内容接近但会导致数组中的数组:
function get_numbers($rest_number) {
$found_number = pow(2, floor(log($rest_number, 2)));
if ($found_number > 0) {
$temp_array[] = get_numbers($rest_number - $found_number);
$temp_array[] = $found_number;
}
return $temp_array;
}
$number_array_recursive = array();
$number_array_recursive = get_numbers($number);
但是,使用像 pow(floor(log()))这样的东西似乎对于像这样的简单问题有点多了。
在我看来,问题需要一个非常简单的数学递归解决方案,但我只是没有看到它。
任何帮助都会被贬低。
编辑:二进制是关键,非常感谢!
答案 0 :(得分:7)
你可以得到数字的二进制表示 - 1表示包括2的幂,0表示不
即
$binary_number = decbin($test_number);
$binary_string = "${binary_number}";
for ($i = 0; $i < strlen($binary_string); $i++) {
if ($binary_string[strlen($binary_string) - $i - 1] == "1") {
$num_out = pow(2, $i);
print "${num_out} ";
}
}
这已经过测试并且可以正常工作,但在PHP语法上可能有更好的方法。
答案 1 :(得分:3)
根据我的经验,递归比循环有更多的开销,所以我建议坚持使用循环解决方案。
答案 2 :(得分:3)
您可以使用以下(未经测试的)功能检查输入数字的每一位。
function checkBit($var, $pos)
{
return ($var & (1 << $pos));
}
通过使用按位AND函数检查变量$ var中位置$ pos的位。为简洁起见,我将向您展示4位数字。
如果我想检查数字3的位置0(最右边的位),我会调用这样的函数:
$number = 3;
checkBit($number, 0);
在内部,checkBit将常量1向左移动0次,因为我传入了0.然后按顺序AND(&amp;)结果与我传入的数字,3。因为3 = 0011 1 = 0001,结果为真,因为在按位AND运算符的两个参数中都设置了第0位。
答案 3 :(得分:1)
如果你只是做了一点点的事情(比如“num&amp; 0x0001”),并检查该操作的值是否为zeroness,那么通过这些位跳闸应该是微不足道的,如下所示: (我知道这是在java中,但我不知道php,反正它并不是特定于php的问题)
int number=25;
for (int i = 0; i < 16; i++)
{
if ((number & 0x0001) != 0)
{
System.out.println("" + Math.pow(2, i));
}
number = number >> 1;
}
这样的事情在任何语言中都应该是微不足道的。
答案 4 :(得分:1)
将整数分解为2的幂的另一种方法是保持除以2并找到余数。
例如: 25/2 = 12 R 1,功率= 2 ^ 0 = 1
12/2 = 6 R 0,功率= 2 ^ 1 = 2
6/2 = 3 R 0,功率= 2 ^ 2 = 4
3/2 = 1 R 1,功率= 2 ^ 3 = 8
1/2 = 0 R 1,功率= 2 ^ 4 = 16
所以,这里25 = 1 + 8 + 16,因为这些是剩余部分为1的唯一地方。
function powers_of_2($n)
{
$powers = array();
$base = 1;
while ($n > 0)
{
if ($n % 2 == 1)
{
$powers[] = $base;
}
$n = (int)$n/2;
$base *= 2;
}
return $powers;
}
答案 5 :(得分:0)
除非您的数字非常稀疏(即number_array会很小),否则通过所有权力可能会更快。坚持基础2:
function get_powers_of_2($n) {
// $max_pow = 31; // faster if you know the range of $n
$max_pow = log($n, 2); // safe
$powers = array();
for($i = 0; i <= $max_pow; $i++) {
$pow = 1 << $i;
if($n & $pow) $powers[] = $pow;
}
return $powers;
}