Using an unsigned int in a do-while loop - c

I'm new to coding in c and I've been trying to wrap my head around unsigned integers. This is the code I have:
#include <stdio.h>
int main(void)
{
unsigned int hours;
do
{
printf("Number of hours you spend sleeping a day: ");
scanf(" %u", &hours);
}
while(hours < 0);
printf("\nYour number is %u", hours);
}
However, when I run the code and use (-1) it does not ask the question again like it should and prints out (Your number is 4294967295) instead. If I change unsigned int to a normal int, the code works fine. Is there a way I can change my code to make the unsigned int work?
Appreciate any help!

Is there a way I can change my code to make the unsigned int work?
Various approaches possible.
Read as int and then convert to unsigned.
Given "Number of hours you spend sleeping a day: " implies a small legitimate range about 0 to 24, read as int and convert.
int input;
do {
puts("Number of hours you spend sleeping a day:");
if (scanf("%d", &input) != 1) {
Handle_non_text_input(); // TBD code for non-numeric input like "abc"
}
} while (input < 0 || input > 24);
unsigned hours = input;

An unsigned int cannot hold negative numbers. It is useful since it can store a full 32 bit number (twice as large as a regular int), but it cannot hold negative numbers So when you try to read your negative unsigned int, it is being read as a positive number. Although both int and unsigned int are 32 bit numbers, they will be interpreted much differently.

I would try the next test:
do:{
printf("enter valid input...")
scanf("new input...")
} while (hours > 24)
Why should it work?
An unsigned int in C is a binary number, with 32 bit. that means it's max value is 2^32 - 1.
Note that:
2^32 - 1 == 4294967295. That is no coincidence. Negative ints are usually represented using the "Two's complement" method.
A word about that method:
When I use a regular int, it's most significant bit is reserved for sign: 1 if negative, 0 if positive. A positive int than holds a 0 in it's most significant bit, and 1's and 0's on the remaining coordinates in the ordinary binary manner.
Negative ints, are represented differently:
Suppose K is a positive number, represented by N bits.
The number (-K) is represented using 1 in the most significant bit, and the POSITIVE NUMBER: (2^(N-1) - K) occupying the N-1 least significant bits.
Example:
Suppose N = 4, K = 7. Binary representation for 7 using 4 bit:
7 = 0111 (The most significant bit is reserved for sign, remember?)
-7 , on the other hand:
-7 = concat(1, 2^(4-1) - 7) == 1001
Another example:
1 = 0001, -1 = 1111.
Note that if we use 32 bits, -1 is 1...1 (altogether we have 32 1's). This is exactly the binary representation of the unsigned int 4294967295. When you use unsigned int, you instruct the compiler to refer to -1 as a positive number. This is where your unexpected "error" comes from.
Now - If you use the while(hours>24), you rule out most of the illegal input. I am not sure though if you rule out all illegal input. It might be possible to think of a negative number such that the compiler interpret it as a non-negative number in the range [0:24] when asked to ignore the sign, and refer to the most significant bit as 'just another bit'.

Related

Unsigned Short Division for binary representation in C

So I am trying to do an integer division on a binary representation of an unsigned short. For example: Say the Unsigned Short x=5, the binary number representation is
1111. 7 would be 111. I want to be able to find the number of Pairs of the 1's bit representation. My idea was to count the number of 1's using bit manipulation as follows.
unsigned short divide(unsigned short input) {
unsigned short count = 0;
while (input != 0){
if ((input & 1) == 1)
count = count + 1;
input = input >> 1;
}
return count;
}
The above code works for getting the total number of 1 bits in a binary representation. Example: in my 7, it would return 3 since there are 3 1's in the binary representation. Now I just want to be able to perform integer division such as 3/2=1 to find the number of 1 pairs. 3/2 for an unsigned short would be 1 since there are only 1 pair of 1's bits. if for 5, it would be 4/2=2. 2 pairs. How would I go about in terms of implementing a integer division without using arithmetic operations such as modulus, +,-,*,/.

How to create a negative binary number using signed/unsigned in C?

My thoughts: if one declares an int it basically gets an unsigned int. So if I need a negative value I have to explicitly create a signed int.
I tried
int a = 0b10000101;
printf("%d", a); // i get 138 ,what i've expected
signed int b = 0b10000101; // here i expect -10, but i also get 138
printf("%d", b); // also tried %u
So am I wrong that an signed integer in binary is a negative value?
How can I create a negative value in binary format?
Edit Even if I use 16/32/64 bits I get the same result. unsigned/signed doest seems to make a difference without manually shifting the bits.
If numbers are represented as two's complement you just need to have the sign bit set to ensure that the number is negative. That's the MSB. If an int is 32 bits, then 0b11111111111111111111111111111111 is -1, and 0b10000000000000000000000000000000 is INT_MIN.
To adjust for the size int(8|16|64)_t, just change the number of bits. The sign bit is still the MSB.
Keep in mind that, depending on your target, int could be 2 or 4 bytes. This means that int a=0b10000101 is not nearly enough bits to set the sign bit.
If your int is 4 bytes, you need 0b10000000 0000000 0000000 00000000 (spaces added for clarity).
For example on a 32-bit target:
int b = 0b11111111111111111111111111111110;
printf("%d\n", b); // prints -2
because int a = 0b10000101 has only 8 bits, where you need 16 or 32. Try thi:
int a = 0b10000000000000000000000000000101
that should create negative number if your machine is 32bits. If this does not work try:
int a = 0b1000000000000101
there are other ways to produce negative numbers:
int a = 0b1 << 31 + 0b101
or if you have 16 bit system
int a = 0b1 << 15 + 0b101
or this one would work for both 32 or 16 bits
int a = ~0b0 * 0b101
or this is another one that would work on both if you want to get -5
int a = ~0b101 + 1
so 0b101 is 5 in binary, ~0b101 gives -6 so to get -5 you add 1
EDIT:
Since I now see that you have confusion of what signed and unsigned numbers are, I will try to explain it as simple as possible int
So when you have:
int a = 5;
is the same as:
signed int a = 5;
and both of them would be positive. Now it would be the same as:
unsigned int a = 5;
because 5 is positive number.
On the other hand if you have:
int a = -5;
this would be the same as
signed int a = -5;
but it would not be the same as following:
unsigned int a = -5;
the first 2 would be -5, the third one is not the same. In fact it would be the same if you entered 4294967291 because they are the same in binary form but the fact that you have unsigned in front means that compiler would store it the same way but treat it as positive value.
How to create a negative binary number using signed/unsigned in C?
Simply negate the constant of a positive value. To attempt to do so with many 1's
... 1110110 assumes a bit width for int. Better to be portable.
#include <stdio.h>
int main(void) {
#define NEGATIVE_BINARY_NUMBER (-0b1010)
printf("%d\n", NEGATIVE_BINARY_NUMBER);
}
Output
-10

Integer range and Overflow

This is a simple program to convert positive decimal number into binary. I have to report and stop conversion of those numbers which could cause overflow or erroneous results. I found size of integer is 4 Bytes but it converts correctly upto 1023 only.
I am confuse where the number "1023" came from? Is there any method to calculate so i can predict what will be the correct range, if say, i am programming on another system.
#include<stdio.h>
int main(void)
{
int decimal,binary=0,y,m=1;
scanf("%d",&decimal);
if(decimal<=1023)
{
while(decimal>0)
{
y=decimal%2;
binary=binary+(m*y);
m=m*10;
decimal=decimal/2;
}
printf("\nBinary Equivalent is: %d",binary);
}
else
{printf("Sorry, The Number You've entered exceeds the maximum allowable range for conversion");}
getch();
return 0;
}
1023 is equal to 1024-1 (2^10 -1), so a number lesser than or equal to 1023 will have 10 digits in base 2. Since you are using an int to get the result, it stores up to 2^31-1 = 2147483647 (31 because one of the 32 bits is used to represent the sign (+ or -)). When you have a 1024 or higher number, it uses more than 10 digits - and, thus, is higher than 2147483647.
Hope that helps.
Actually, the range of an integer is between [-2^31, 2^31-1]. Because there are 4 bytes (i.e., 32 bits). However, if you want to scanf a non-negative integer. you have to initial a unsigned int rather int. The range will be [0, 2^32-1].
The problem is in the temporary variables binary and m you use. Because 1024 would take 11 divisions to become 0, m will become 10.000.000.000. However, the maximum value of an int is 2.147.483.647 (since one bit of the four bytes is used as a sign bit). m will thus overflow, which results in an incorrect result. 1023 or smaller values will take 10 devisions or less to become 0, so m is max 1.000.000.000, so m has no overflow.
You seem to want to take a 4 byte decimal number and convert it to a binary string of 0s and 1s. The method used in the code fails when the decimal number is > 1023. Here is a conversion that produces a string of 0s and 1s that can be printed using:
printf("\nBinary Equivalent is: ");
while( int i = 0; i < 32; i++ )
{
printf( "%c", (decimal & (1<<i) )? '1': '0');
}
printf("\n");
This eliminates much of the code clutter and produces the desired output.

assumption on floating point conversion: (int)(float)n == n

May I assume that (int)(float)n == n for any int n? At least I need this for non-negative, 31 bits values.
addendum. What about (int)(double)n ==n?
No, you can't. For ints that can't be represented exactly by a float, this will fail.
(The reason: float is generally a 32-bit IEEE-754 floating-point value. It only has 24 bits of precision, the rest is reserved for the exponent and the sign. So if your integer has more significant binary digits than 23, and it doesn't happen to be a multiple of an appropriate power of two, then it can't be represented precisely as a float.)
addendum. What about (int)(double)n ==n?
It's the same. For ints that can't be represented as a double, the comparison won't always yield true. However, generally, int is not long enough to accomplish this -- the widely-accepted implementation of double is a 64-bit IEEE-754 floating-point number which has 53 bits of precision, whereas ints tend to be at most 32 bits long. But you can always try to repeat the experiment with a long or a long long and a double instead.
Here's a demo:
#include <stdio.h>
int main()
{
int n = (1 << 24) + 1;
printf("n == n: %d\n" , n == n);
printf("n == (int)(float)n: %d\n", n == (int)(float)n);
return 0;
}
This prints:
n == n: 1
n == (int)(float)n: 0

Using bit with int in structure

#include<stdio.h>
struct a
{
int a:4;
};
main(){
struct a aa;
aa.a=9;
printf("a=%d\n",aa.a);
return 0;
}
Here the output is -7. Why is it so?
what does exactly int a:4 does ? please explain
Since it's two's complement, the highest order bit is used for the sign. By writing a:4 you're saying to only allocate 4 bits of memory, which leaves 3 bits left over for the actual number. So our effective range is [-8,7]. Since all 1's is -1, there's an extra number on the negative side. For more of an explanation on this, see the above link.
9, in (unsigned) binary is: 1001. When you put this into a (signed), you get that a is negative, due to the initial 1, and since the following numbers are 001, we add 1 to the max negative number, thereby giving us -7.
If you want to store the number 9 in only 4 bits, you need to use an unsigned int, which would give you a range of [0, 15].
EDIT:
In case anyone is struggling with figuring out how 1001 signed gives us -7, consider the following:
Since 1111 is -1, let some variable value = -1.
To figure out the values of a negative (signed) int num, let us denote xi in num:
xi : {0,1 at position i, where i=0 is the least significant bit)},
Then, for every xi = 0, subtract 2i from value.
Example:
1001:
value = -1 - 21 - 22 = -7
Your field is a 4 bit signed integer. For signed integers the upper bit is a sign bit, which means that you only have 3 bits for the actual number. The range of numbers you can store in the field are -8 to 7 (assuming 2's compliment storage).
The bit pattern for 9 is 1001, which has the 4th bit set, meaning it is interpreted as a negative number, which is why it is printing out as a -7. If you would have expected a -1, you need to read up on 2's compliment.
If you want to be able to store 9 in the field, make a an unsigned int
You only reserved 4 bits for the field, one bit is used for the sign, so only 3 bits remain for positive values. Thus you can only store values up to 7.
you have to use unsigned indeed int :
#include<stdio.h>
struct a
{
unsigned a:4; // <-- unsigned indeed int, then work good
};
main(){
struct a aa;
aa.a=9;
printf("a=%d\n",aa.a);
return 0;
}
output :
a=9

Resources