我参加了考试,从那以后我一直在努力。 你有一个整数数组(例如13,6,21,4),我需要做一个看起来像这样的输出:
13 = 2^3 + 2^2 + 2^0
6 = 2^2 + 2^1
21 = 2^4 + 2^2 + 2^0
4 = 2^2
这是我到目前为止所得到的。
#include <stdio.h>
#define MAX 100
int main() {
int niz[MAX], nizb, n, i, ones, k;
while(1) {
printf("Array length: ");
scanf("%d", &n);
if (n<=0 || n>MAX) break;
printf("Array elements: ");
for(i=0;i<n;i++){
scanf("%d", &niz[i]);
if (niz[i] <=0) {
printf("Error! Wrong value. Enter new one: ");
scanf("%d", &niz[i]);
}
}
for(i=0;i<n;i++) {
nizb = niz[i];
ones = 0;
for(k=0; k < 16; k++) {
//What should i do here?
}
}
}
}
我被困在这里。我不知道我应该使用多少位,以及C如何看到这些整数位。我正在使用var'k'添加到格式为'2 ^ 3 + 2 ^ 2 ...'的字符串,其中k是'for'迭代的值。我假设整数的长度是16,但我真的不确定,因为我们在一张纸上这样做。
我想对每个人都说得好!
答案 0 :(得分:2)
您可以使用sizeof
运算符和CHAR_BIT
来计算要使用的位数:
int bitsPerInt = sizeof(int) * CHAR_BIT;
CHAR_BIT
在limits.h
中定义。
有了这个限制后,你可以使用按位&
运算符来提取每个位:
for (k = bitsPerInt - 1; k >= 0; k--)
{
if (nizb & (1U << k))
// output
else
// don't
}
我会把细节留给你。
除此之外:看起来您正在尝试将niz
用作数组,但您尚未将其声明为一个数组。这段代码甚至可以编译吗?此外,main
的返回值应为int
。
答案 1 :(得分:1)
这是完全猜想,因为我对数学不是很好,但我想我会这样做:
int potency = 0, base = 1;
while(base < NumberInQuestion) {
base *= 2;
++potency;
}
循环结束后,您将知道仍然适合“数字”的最高效力。
Number -= base/2; //Removes the base you just calculated from the number.
printf("2^%d", potency);
冲洗并重复,直到Number降至0,最迟应为2 ^ 0。
对于您的用例,代码可能看起来像这样:
for(i=0; i < n; ++i) {
int Number = niz[i];
while(Number > 0) {
int potency = 0, base = 1;
do { //Executes at least once, making a number of '1' possible.
base *= 2;
++potency;
} while(base < Number);
Number -= base/2; //Reverts the last step you made, making the 'base' smaller than 'Number'.
printf("2^%d", potency);
}
}
有一种可能的选择,它可以让您更全面地了解事物并节省迭代次数。为此,我们使用两个步骤。
for(i=0; i < n; ++i) {
int Number = niz[i];
int potency = 0, base = 1;
do { //Executes at least once, making a number of '1' possible.
base *= 2;
++potency;
} while(base < Number);
base /= 2; //Reverses the last iteration.
//At this point, we know the maximum potency, which still fits into the number.
//In regards of base 2, we know the Most Significant Bit.
while(base > 0) {
Number -= base; //Removes the MSD (Most significant digit)
printf("2^%d", potency); //Prints your '1'.
while(base > Number) { //Executes at least once.
base /= 2; //Goes back one potency. (Ends at '0' latest.)
--potency; //For each potency (except for first), it's a '0'.
}
}
}
答案 2 :(得分:1)
不确定这与二元补码(这是表示负数的特定方式)有什么关系。你要做的是将一个整数表示为2的幂的总和,显然。这是我做的方式,这不一定比其他答案更好或更差......
void powersum(int n)
{ int powers[sizeof(int) << 3];
int i;
char *sep = "";
printf("%d = ", n);
powers[0] = 0;
for (i = 0; n; n >>= 1, ++i)
powers[i] = n & 1;
while (--i >= 0)
{ if (powers[i])
{ printf("%s2^%d", sep, i);
sep = " + ";
}
}
printf("\n");
}
编辑:这是另一个不使用堆栈分配数组的版本,但是因为权衡必须更多地循环(每个位一次,而不是仅循环直到找到最高的1位) :
void powersum2(int n)
{ int i = (sizeof(int) << 3) - 2;
int m = 1 << i;
char *sep = "";
printf("%d = ", n);
while (m)
{ if (n & m)
{ printf("%s2^%d", sep, i);
sep = " + ";
}
m >>= 1;
--i;
}
printf("\n");
}
答案 3 :(得分:0)
quotient = niz[i];
int k=0,c[MAX];
while(quotient!=0){
binaryNumber[i++]= quotient % 2; //this will convert your numbers to binary form
quotient = quotient / 2; //and store in reverse in array
}
for(j = 0 ;j<i;j++)
{
if(binaryNumber[j]==1) */e.g binary of 4 is stored in array as 001 ie 1 atpos2*/
{ c[k]=j;
k++;}
}
while(k--)
printf("2^%d +",c[k]);
答案 4 :(得分:0)
如果你能够容忍GCC依赖,那么对@ twalberg解决方案的破解真的很好而且很小;)
void powersum(int n)
{
char *sep = "";
printf("%d = ", n);
while (n) {
int pos = 31 - __builtin_clz(n);
printf("%s2^%d", sep, pos);
sep = " + ";
n ^= 1 << pos;
}
printf("\n");
}