[英]Fill array with binary numbers
First of all this is not homework! 首先这不是功课!
My question is from the book: Algorithms in C++ third edition by Robert Sedgewick. 我的问题来自于 Robert Sedgewick所著的《 C ++算法》第三版 。
There is given an array of size n by 2^n (two dimensional) and we should fill it with binary numbers of bits size exactly n. 给定大小为n乘2 ^ n(二维)的数组,我们应该用二进制数正好为n的位数填充它。 For example for n=5 the result will be: 例如对于n = 5,结果将是:
00001
00010
00011
00100
00101
00110
00111
And so on. 等等。 We should put this sequence of bits into arrays. 我们应该将此位序列放入数组中。
I do not know much C/C++, but a naïve, language-agnostic approach would be to simply find a formula for A[i, j], where i \\in [0, 2^n - 1] and j \\in [0, n-1]. 我不太了解C / C ++,但是一种幼稚的,与语言无关的方法将是简单地找到A [i,j]的公式,其中i \\ in [0,2 ^ n-1]和j \\ in [ 0,n-1]。
In words, A[i, j] contains the jth binary digit of i, counting from the most significant bit. 换句话说,A [i,j]包含i的第j个二进制数,从最高有效位开始计数。
In formulae, A[i, j] = (i AND 2^(n-1-j) ) SHR (n-1-j) 在公式中,A [i,j] =(i AND 2 ^(n-1-j))SHR(n-1-j)
where AND is the binary bitwise and operator, and SHR is the binary "shift bits right" operator. 其中AND是二进制按位与运算符,而SHR是二进制“右移位”运算符。 a^b means (of course) "a raised to the power of b". a ^ b的意思是(当然)“ a提升为b的幂”。
Ugly Proof-Of-Concept Delphi Code: 丑陋的概念验证Delphi代码:
var
i: Integer;
twoton: integer;
j: Integer;
begin
twoton := round(IntPower(2, n));
SetLength(A, twoton, n);
for i := 0 to twoton - 1 do
for j := 0 to n - 1 do
A[i, j] := (i and round(IntPower(2, n-1-j))) shr (n-1-j);
This works perfectly, but I am quite sure there are faster ways... At least one could store the powers of 2 in an array and use POWEROF2[k] rather than round(IntPower(2, k)), but - of course - this depends on your language. 这可以正常工作,但是我很确定有更快的方法……至少一个可以将2的幂存储在数组中,并使用POWEROF2 [k]而不是round(IntPower(2,k)),但是-当然-这取决于您的语言。 After all, IntPower is a Delphi function. 毕竟,IntPower是Delphi函数。
How this works 如何运作
Say that we have the number 23, or, in binary 10111. Now we want the third binary digit. 假设我们有数字23,或二进制10111。现在我们要第三个二进制数字。 Then we want to AND the number 10111 with the number 00100, to obtain 00100 if the sought digit is one, and 00000 otherwise. 然后,我们要对10111和00100进行“与”运算,如果要查找的数字为1,则为00100,否则为00000。 Notice that 00100, the number we AND with, is simply 2^3 in decimal; 请注意,与我们进行运算的数字00100只是十进制2 ^ 3; hence all powers-of-2. 因此所有2的幂。 Now we have the number 00N00, where N is the sought digit, in this example 1: 00100. We now shift the bits of this number 3 steps to the right (the SHR operation), to obtain 00001 = 1, and - voilà! 现在我们有了数字00N00,其中N是要查找的数字,在本例中为1:00100。我们现在将该数字的位向右移动3步(SHR操作),以获得00001 = 1,并且-voilà! - we have gotten our digit! -我们已经掌握了数字!
A Smarter Approach 更聪明的方法
I do not know how C stores arrays, but you could simply create a 2^N-dimensional vector A of unsigned integers (8-bit, 16-bit, or 32-bit, preferably), namely the numbers 0, 1, 2, ..., 2^N - 1, and then argue that this actually is a two-dimensional matrix . 我不知道C如何存储数组,但是您可以简单地创建一个2 ^ N维向量 A,该向量 A是无符号整数(最好是8位,16位或32位),即数字0、1、2 ,...,2 ^ N-1,然后认为这实际上是一个二维矩阵 。 Indeed, if we introduce the notation UNSINGED_INTEGER[k] as the kth bit of UNSIGNED_INTEGER, then A[i][k] is more or less the matrix you wanted... 确实,如果我们将符号UNSINGED_INTEGER [k]引入UNSIGNED_INTEGER的第k位,则A [i] [k]或多或少是您想要的矩阵...
Each number is one more than the last in the binary number system. 每个数字都比二进制数字系统中的最后一个数字大一个。
To increment (add one) in binary 以二进制递增(加一)
Note that the <<
operator multiplies the left operand by two to the power of the right operand. 请注意, <<
操作符将左侧操作数乘以2等于右侧操作数的幂。 The number 1l
is simply 1
expressed as a long
, which is 64 bits on a 64-bit system. 数字1l
简单地用1
表示为long
,在64位系统上为64位。
template< size_t n > // template detects size of array. Strictly optional.
void ascending_binary_fill( bool (&arr)[ 1l << n ][ n ] ) {
std::fill( arr[0], arr[0] + n, 0 ); // first # is 0
for ( size_t pred = 0; pred < 1l << n; ++ pred ) {
int bit = n; // pred = index of preceding number; bit = bit index
while ( arr[ pred ][ -- bit ] ) { // trailing 1's in preceding #
arr[ pred+1 ][ bit ] = 0; // ... are trailing 0's in current #
}
arr[ pred+1 ][ bit ] = 1;
std::copy( arr[ pred ], arr[ pred ] + bit, arr[ pred+1 ] );
}
}
Quite simple! 非常简单!
here is a solution in pseudocode 这是伪代码的解决方案
assert(bits <= 32)
int array[pow(2, bits)]
for (uint i= 0; i < length(array); i++)
array[i]= i;
The result is an array filled with the pattern you gave as an example 结果是一个数组,其中填充了您作为示例给出的模式
public static uint[][] FillUpCode(uint qValue, uint kValue)
{
var size = (ulong)Math.Pow(qValue, kValue);
var array = new uint[size][];
var workArray = new uint[kValue];
long position = kValue - 1;
ulong n = 0;
while (position > 0)
{
while (workArray[position] < qValue)
{
var tempArray = new uint[kValue];
Array.Copy(workArray, tempArray, kValue);
array[n++] = tempArray;
workArray[position]++;
}
while (position > 0)
{
workArray[position] = 0;
if (workArray[position - 1] < (qValue - 1))
{
workArray[position - 1]++;
position = kValue - 1;
break;
}
position--;
}
}
return array;
}
qValue - number base, kValue - line length :) Code may be useful when you need to generate array in different number basis. qValue-数字基,kValue-行长:)当您需要以其他数字基生成数组时,代码可能会很有用。
// My solution is based on that of Potatoswatter.
// use cols value where rows = 2^cols
// start here after setting cols
rows = pow(2.0, double(cols));
// memory allocation
bool **array = new bool*[rows];
for (int i = 0; i < rows; i++) {
array[i] = new bool[cols];
}
std::fill( array[0], array[0] + cols, 0 ); // maybe not needed
for (int i = 1; i < rows; i++) { // first row is zero, start at second
// starting at right ...
int j = lits - 1;
// turn the last zero into a one
if (array[i][j] == false) {
array[i][j] = true;
}
else {
// turn all trailing ones into zeros (prior to first zero)
while (array[i][j] == true) {
array[i][j] = false;
j--;
}
array[i][j] = true;
}
// copy this row to next row
if (i < (rows - 1)) {
std::copy(array[i], array[i] + lits, array[i+1]);
}
}
So basically, you need an array that starts at zero, and goes up to 2^n? 因此,基本上,您需要一个从零开始到2 ^ n的数组?
Psuedo-C: 伪C:
bool[][] Fill(int n) { max = Pow(2, n); array = new bool[max, n]; for i from 0 to max - 1 for j from 0 to n - 1 array[i][n - j - 1] = ((i >> j) & 1) == 1; return array; }
The only problem I can see with that is that it capped at n = 32, but that will already take enormous amounts of memory so that really is a non-issue. 我可以看到的唯一问题是它的上限为n = 32,但这已经占用了大量内存,因此实际上不是问题。
Note that you could as well make it a one dimensional number and fill it with numbers from 0 to 2^n, and the A[i][j]th element will actually be retrieved using (A[i]>>j) & 1. 请注意,您也可以将其设为一维数,并用0到2 ^ n的数字填充,实际上将使用(A [i] >> j)&检索第A [i] [j]个元素1。
This is a very rudimentary problem, and I will demonstrate with this Java snippet: 这是一个非常基本的问题,我将通过以下Java代码片段进行演示:
public class Bin { // prints:
static String zero(int L) { // 0000
return (L <= 0 ? "" : String.format("%0" + L + "d", 0)); // 0001
} // 0010
static String zeroPad(String s, int L) { // 0011
return zero(L - s.length()) + s; // 0100
} // 0101
public static void main(String[] args) { // 0110
final int N = 4; // 0111
for (int i = 0; i < (1 << N); i++) { // 1000
System.out.println(zeroPad(Integer.toBinaryString(i), N)); // 1001
} // 1010
} // 1011
} // 1100
// 1101
// 1110
// 1111
I will leave it to you to figure out how to implement toBinaryString
and how to populate int[][]
with the bits. 我将留给您了解如何实现toBinaryString
以及如何使用这些位填充int[][]
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.