I am beginner in C and can't understood how this piece of code is working:
struct marks{
int p:3;
int c:3;
int m:2;
};
void main(){
struct marks s={2,-6,5};
printf("%d %d %d", s.p, s.c, s.m);
}
I found that the output is: 2 2 1
But after a lot of try I was unable to figure out how the output is like that. I have less knowledge about the struct. That's why may be I am feeling some problem here.
Well, inside the struct you defined- p:3, c:2, m:2 are actually denoting the bit fields. To know more about bit fields in C go through this link in SO or this link in Wikipedia.
For simplicity, know that the 3 or 2 after the colon(:) sign is representing bit-fields of width 3 or 2. That means 3 or 2 adjacent computer memory locations which have been allocated to hold a sequence of bits.
Now, inside the main() function of your code:
struct marks s={2,-6,5};
Here,
Binary value of 2: 00000010
Binary value of -6: 11111010
Binary value of 5: 00000101
Now according to bit-fields, from binary value of 2, we will take last 3 digits which is 010 (in decimal it is 2) and from binary value of -6, we will take last 2 digits which is 10 (in decimal it is 2) and from binary value of 5, we will take last 3 digits which is 01 (in decimal it is 1) and finally assign them to p, c or m.
That's how the output comes as 2 2 1.
Hope, I could make you clear.
first of all your declaration of struct is using bit fields.
struct marks{
int p:3;
int c:3;
int m:2;
};
here p:3 means we are defining P to be an int and we are preserving only 3 bit of the given number. For example , You need 3 bits to represent the value 5, which would be represented as 101. The lower 2 bits are the value 1. That's why you get m=1.
This link will give you more explanation.
Thanks.
Related
I want to obtain the binary logarithms of the numbers 1 to 2048, but I don´t know why it doesn´t work, it doesn´t obtain the right numbers.
If I use floats, it works, but it used to work with integers, i have already done a program with this method and now it doesn´t work because of that. Changing the unsigned int to int doesn´t work. Someone knows why?
for(unsigned int numero=1;numero<=2048;numero*=2)
{
int x=log10(numero)/log10(2);
printf("%d\n",x);
}
return 0;
It prints:
0 1 2 2 4 5 5 6 8 9 10 11
It should be:
0 1 2 3 4 5 6 7 8 9 10 11
Looks like it works for some numbers, but i don´t understand why it doesn´t work for all numbers.
log10 returns a floating point number (double). The value of log10 is not exactly representible in floating point for most numbers you pass, therefore you might get something like log10(8)/log10(2) == 2.9999999 instead of an exact 3. The conversion to int truncates it down to 2. To fix that you should round properly:
int x = lrint(log10(numero)/log10(2));
Or in case your compiler doesn't have the lrint function you can use:
int x = log10(numero)/log10(2) + 0.5;
which would work for this case.
Notice that there are alternative ways to calculate the desired result. Since floating-point numbers already store the exponent in base 2, you can retrieve it with a call to frexp:
int x;
frexp(numero, &x);
Another way would be to avoid floating point math altogether and use an intrinsic to get the index of the last bit set in numero. Unfortunately there's no cross-platform way to do that.
I came across this program to convert decimals numbers into their binary equivalent in C. I do not understand how the printf statement works in this program.
int main()
{
int N;
scanf("%d", &N); // Enter decimal equivalent here
for( int j = floor(log2(N)); j >= 0; j-- ){
printf("%d", (N >> j) & 1);
}
}
Let's take an example to get through this problem. Suppose you enter N=65. Its binary representation is - 1000001. When your given code goes through it, j will start at floor(log2(65)), which is 6. So, the given loop will run 7 times, which means 7 numbers will be printed out (which fits the fact that 65's binary representation has 7 digits).
Inside the loop - The number is shifted by j bits each time to the right. When 1000001 is shifted to the right by 6 bits, it becomes 0000001. If shifted by 5, it is 0000010, and so on. It goes down to a shift by 0 bits which is the original number. When each of these shifted numbers are &ed with 1, only the least significant bit (the right most bit) remains. And this digit can either be a 0 or a 1.
If you would have noticed each right shift divides the number by 2. So when 1000001 is shifted by 1 to make 0100000, it is the binary representation of 32, which indeed is 65/2 in C. After all, this is the way someone manually calculates the binary representation of a number. Each division by 2 gives you a digit (starting from the end) of the representation, and that digit is either a 0 or a 1. The & helps in getting the 0 or 1.
In the end, 65 becomes 1000001.
What it is doing is:
Finding the largest number j such that 2^j <= N
Starting at the jth bit (counting from the right) and moving to the right ...
chopping off all of the bits to the right of the current chosen bit
chopping off all of the bits to the left of current chosen bit
printing the value of the single remaining bit
The code actually has undefined behavior because you did not include <stdio.h>, nor <math.h>. Without a proper declaration of floor() and log2(), the compiler infers the prototype from the calling context and gets int log2(int) and int floor(int), which is incompatible with the actual definition in the C library.
With the proper includes, log2(N) gives the logarithm of N in base 2. Its integral part is the power of 2 <= N, hence 1 less than the number of bits in N.
Note however that this method does not work for negative values of N and only works by coincidence for 0 as the conversion of NaN to int gives 0, hence a single binary digit.
I have searched many articles on google for following question but still not find any good answer.
From my first look ,I able to get that int x:3 here 3 is width if we assign x value greater than 3 some negative value get printed and if we assign value less than 3 ,the assigned value to x get printed correctly.
Can anyone explain how the output is coming of this code.
#include<stdio.h>
1 struct Point
2 {
3 int x:3, y:4;
4 };
5
6 int main()
7 {
8 struct Point p1 = {6,3};
9
10 printf ("x = %d, y = %d", p1.x, p1.y);
11
12 return 0;
13 }
The output comes as:
x = -2, y = 3
when i included stdio.h header file warning vanished but the output of x get chnaged first without header file the value of x is coming -4 now with stdio.h header file the value of x becomes -2.Why this is happening??
Thanks in advance!!
You are trying to store the value 6 into a signed integer of 3 bits, where there are 2 value bits and 1 bit reserved for the sign. Therefore the value 6, which cannot fit in the 2 value bits, is converted to a signed value in an implementation-defined manner. Apparently by using Two's complement.
"warning: overflow in implicit constant conversion" tells you just that. The compiler tries show constant 6 into the signed type bit field. I cannot fit - you get an overflow, and then there's an implicit type conversion to signed type.
I am trying to convert decimal Nos. into binary. The code works pretty fine (Windows 7 , 32 bit MS-VS2010):
int main()
{
int k, n;
int binary[100];
printf("Enter the value in decimal \n ");
scanf("%d", &k);
n = (log(k * 1.0) / log(2 * 1.0)) + 1 ; //total no. of binary bits in this decimal
for (int i = n; i > 0; i--)
{
binary[i] = k % 2;
k /= 2;
}
return 0;
}
But the limitation is that it works for Int size values only i.e. 32 bit. I want to modify this code so that it works for 2048 bits (decimal numbers containing 617 digits actually). I am not allowed to use any library.
Can someone give me some pointers how to proceed to tackle this?
Can someone give an example code snippet say for 64 bits ? Then I can use this to extend to higher values.
Update
1-As per suggestions I am trying to use strings. But I am not able to understand how to convert an String into large Int (I cant use stoi() as thsi will convert to 32 bit int , right? ).
2- Secondly I have to find:
log(222121212213212313133123413131313131311313154515441315413451315641314563154134156313461316413415635154613415645156451434)
Is the library function log capable of finding this ? Then what is the solution?
Since you told that you just need some pointers and not the actual answer, here goes:
I am not able to understand how to convert an String into large Int
That's because you can't. If you want to convert a number that huge to a numerical type, in the first place you need such a type that can hold numbers that big. The language doesn't provide you anything more than long long which is usually 128-bits long (i.e. if you can use C99, or just long which is usually lesser than a long long). Since your tutor told you not to use any external library, it's a clear sign that s/he wants you to code the solution using what's available only in the language and perhaps additionally the standard library.
Is the library function log capable of finding this
No, you can't use stoi or log since all of these expect arguments of some arithmetic type, while none of those built-in types are that big to hold numbers this huge. So you've to work completely with strings (i.e. either static or dynamic char buffers).
I understand that you want to use log to deduce the number of digits the binary output would need; but there's another option, which is to not know the number of digits before hand and allocate them dynamically with some upper bound so that you needn't re-allocate them further.
Lets take an example.
Allocate 3 char buffers in, out (length of input) and bin (length of input * 4).
Copy input to in
While in is not "0" or "1" do else goto 12
For each element ch in in do else goto 10
Convert ch to integer i
If is_odd = 1 then i += 10
quot = i / 2
Append quot to out
is_odd = quot % 2; goto 4
If is_odd = 1 append '1' else '0' to bin
Copy out to in, reset out and goto 3
Append in to bin
Print bin in reverse
When you integer divide a number by 2, the quotient would always be less than or equal to the number of digits of the dividend. So you could allocate in and out with the same size as the input and use it for all iterations. For the bin buffer, the knowledge that each decimal digit wouldn't take more than 4 bits (9 takes a nibble, 1001) would help. So if the input is 10 digits, then 10*4 = 40 bytes would be the upper limit needed for bin buffer and 10 bytes would be needed for the in and out buffers.
This is a vague write-up of an algorithm, I hope it conveys the idea. I feel writing code is more easier than writing algorithms properly.
I'm afraid there are no standard types in C that will allow you to store such a big value with 20148 bits... You can try to read the string from console (not converting into int), and then parse the string into "010101...." on your own.
The approach would be like that:
You should go for "dividing" the string by 2 in each step (for each division by 2 you need to divide all digits of the string by 2, and handle special cases like 11 / 2 => 5), and for each step if the value cannot be divided by 2, then you then you can put "1" as another binary digit, otherwise you put "0". This way you gather the digits '0', '1', '0', '1', etc. one by one. Then finally you need to reverse the order of digits. A similar approach implemented in C# you can find here: Decimal to binary conversion in c #
Regarding the update:
Grinding it through WolframAlpha gives:
log(222121212213212313133123413131313131311313154515441315413451315641314563154134156313461316413415635154613415645156451434)
is roughly
274.8056791141317511022806994521207149274321589939103691837589..
Test:
Putting it into exp gives:
2.2212121221321231313312341313131313131131315451544131541.. × 10^119
This raises the question about the precision you need.
Note: I assumed you mean the natural logarithm (base e).
This question already has answers here:
Binary numbers with the same quantity of 0s and 1s
(6 answers)
Closed 8 years ago.
I want to convert all integers below 1048576 to binary and display all numbers which have the same number of bits set as unset. My program works fine when I use a table t of 20 integers, in which case cpt records the correct result.
However, when I use a table t of 40 integers (which means I want the numbers with 20 '1' bits and 20 '0' bits) the counter is set to 1. What is wrong?
int main(){
long int a;
int r,j,i;
long int aux;
int z,u;
long int cpt;
int t[40];
for(int k=0;k<40;k++) t[k]=0;
cpt=0;
for(a=0;a<1048576;a++){
j=0;u=0;z=0;
aux=a;
do{
r=aux%2;
switch(r){
case 0 : t[j]=0;
aux=(aux/2);
j++;
break;
case 1 : t[j]=1;
aux=((aux-1)/2);
j++;
break;
}
}while(aux!=0);
for(i=0;i<40;i++){
if(t[i]==0) z++;
else u++;
}
if(z==u) cpt++;
}
printf("%d",cpt);
getchar();
}
Your loop only goes to 1048576, which is 2^20.
Don't you need to loop until 2^40?
Also, note that int may not be 40 bits wide.
Note:
The naive solution to check all numbers doesn't scale well. Perhaps you should consider a smarter solution?
Because only one number in the range [0, 1048576) has exactly as many bits 1 as 0, when counted in your 40 "bit" array.
The flaw in your logic is that you do not examine all numbers in a given range. For instance, when you want to examine all 40-bit integers, you need to iterate until 2^40 and not 2^20.
Lastly, this brute force solution won't work very well for your problem. Instead, try to consider the pattern that appears when you examine the number of paths from the top-left node and proceeding to the down or right for a small array on a piece of paper. Does one emerge? If you're math-inclined, you will instantly recognise it; otherwise, take a minute to look through the binomial coefficients.
As others have said, the main thing that is wrong is the algorithm you are using (exhaustive search); you would need to loop from 0 to 240-1 to iterate across the entire set of numbers to be tested (rather than to 220-1), which would be an impractical number of iterations, not least as there are faster ways.
Consider the maths of the problem: you want a 40 bit field, with 20 bits set to 1. So, you are choosing 20 things from 40. Think about the nCr (combination operator from permutations and combinations); that will give you the link to the binomial coefficients. Now think how you might write an algorithm to go through every combination.
Your code would also be more comprehensible if it did not have single letter variable names, and had some comments explaining what it was meant to be doing.
If you are having difficulty remembering the bit width of integer types, I suggest you use
#include <stdint.h>
and use types like int64_t which is guaranteed to be 64 bits. See:
http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/stdint.h.html
(Note that OP apparently wanted a list of the numbers with 20 bits set, rather just the count of such numbers, so merely looking at binomial coefficients is insufficient).
try using a long long int:
unsigned long long int a;
to fasten and clear a lot of code try also using popcount, it's a function that returns the number of 1-bits in x: http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html.
//I'm not 100% sure if the popcount will work with long long ints, but you can try.
BTW I have a question about the same euler problem #: Binary numbers with the same quantity of 0s and 1s