Character to binary function doesn't work as expected - c

I have made a function to translate a number to its binary form:
size_t atobin (char n)
{
size_t bin= 0, pow;
for (size_t c= 1; n>0; c++)
{
pow= 1;
for (size_t i= 1; i<c; i++) //This loop is for getting the power of 10
pow*= 10;
bin+= (n%2)*pow;
n/= 2;
}
return bin;
}
It works great for numbers 1 to 127, but for greater numbers (128 to 255) the result is 0... I've tried using the type long long unsigned int for each variable but the result was the same. Someone has an idea about why?

char by default in C is considered to be of signed.
char is of 8 bits(mostly). And for signed char the MSB is used for sign. As a result you can only use 7 bits.
(0111 1111)2 = (127)10 The maximum value that your fucntion can work with. (as you are passing a type of variable which can hold 127 at max).
If you use unsigned char then the MSB is not used as sign-bit. All 8 bits are used giving us a maximum possible value (1111 1111)2 = (255)10
For signed number min/max value is -127 to +127.
For unsigned number min/max value is 0 to +255.
So even if you make the type of the passed parameter unsigned char the maximum value it can hold is +255.
A bit more detail:
Q) What happens when you assign >127 values to your char parameter?
It is signed char by default. It is of 8 bits. But it can't hold it. So what will happen?
The result is implementation defined. But
Suppose the value is 130. In binary it is 10000010. In most of the cases this returns -126. So that will be the value of n.
n>0; fails. Loop is never entered. And it returns 0.
Now if we make it unsigned char then it can hold values between 0 and 255 (inclusive). And that is what you want to have here.
Note:
Q) What happens when >255 values are stored in unsigned char?
The value is reduced to modulo of (max value unsigned char can hold+1) which is
256.
So apply modulo operation and put the result. That will be stored in
unsigned char.

Related

what is behavior when char is compared with unsigned short in c language?

When I run the following program:
void func(unsigned short maxNum, unsigned short di)
{
if (di == 0) {
return;
}
char i;
for (i = di; i <= maxNum; i += di) {
printf("%u ", i);
}
printf("\n");
}
int main(int argc, char **argv)
{
func(256, 100);
return 0;
}
It is endless loop, but i wonder when char is compared with unsigned short, is char translated to unsigned short? In this situation, char is overflow and larger than maxNum. I really do not know how to explain the results of this program.
Implementation defined behavior, Undefined behavior and CHAR_MAX < 256
Let us sort out:
... unsigned short maxNum
... unsigned short di
char i;
for (i = di; i <= maxNum; i += di) {
printf("%u ", i);
}
char may be a signed char or an unsigned char. Let us assume it is signed.
unsigned short may have the same range as unsigned when both are 16-bit. Yet it is more common to find unsigned short as 16-bit and int, unsigned as 32-bit.
Other possibles exist, yet let us go forward with the above two assumptions.
i = di could be interesting if the value assigned was outside the range of a char, but 100 is always within char range, so i is 100.
Each argument in i <= maxNum goes through usual integer promotions so the signed char i first becomes an int 100 and the 16-bit maxNum becomes an int 256. As 100 < 256 is true, the loop body is entered. Notice i would never expect to have a value as large as 256 since CHAR_MAX is less than 256 - even on following loops - This explains the seen forever loop. But wait there's more
With printf("%u ", i);, printf() expects a matching unsigned argument. But i as a type with less range then int gets promoted to a int with the same value as part of a ... argument. Usually printing mis-matched specifiers and type is undefined behavior with an exception: when the value is representable as both a signed and unsigned type. As 100 is the first time, all is OK.
At the loop end, i += di is like i = i + di;. The addition arguments go through usual integer promotions and become int 100 added to int 100. That sum is 200. So far nothing strange. Yet assigning a 200 to a signed char coverts the 200 as it is out of range. This is implementation defined behavior. The assigned value could have been 0 or 1 or 2.... Typically, the value is wrapped around ("modded") by adding/subtracting 256 until in range. 100 + 100 -256 --> -56.
But the 2nd printf("%u ", i); attempts printing -56 and that is undefined behavior.
Tip: enable all warnings, Good compilers will point out many of these problems and save you time.
I got the answer from http://www.idryman.org/blog/2012/11/21/integer-promotion/ , both char and unsigned short are translated to int which can explain the process and result of this programs.

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

Incorrect value printed by the 'pow' function in C

Why does the below code gives 127 as output, when it has to be 128. i have even tried to figure out, but I don't understand why 127?
#include<stdio.h>
#include<math.h>
int main()
{
signed char ch;
int size,bits;
size = sizeof(ch);
bits = size * 8;
printf("totals bits is : %d\n",bits);
printf("Range is : %u\n", (char)(pow((double)2, (double)(7))));
}
If you want 128 as result then typecast pow() result as int instead of char. for e.g
printf("Range is : %u\n", (int)(pow((double)2, (double)(7)))); /* this print 128 */
Why this
printf("Range is : %u\n", (char)(pow((double)2, (double)(7))));
prints 127 as pow((double)2,(double)7) is 128 but at same time that whole result vale explicitly type casted as char and default char is signed which ranges from -128 to +127 , hence it prints 127.
Side note, pow() is floating point function as #lundin suggested & same you can find here. you can use
unsigned char ch = 1 << 7;
to get the same in particular case.

summing unsigned and signed ints, same or different answer?

If I have the following code in C
int main()
{
int x = <a number>
int y = <a number>
unsigned int v = x;
unsigned int w = y;
int ssum = x * y;
unsigned int usum = v * w;
printf("%d\n", ssum);
printf("%d\n", usum);
if(ssum == usum){
printf("Same\n");
} else {
printf("Different\n");
}
return 0;
}
Which would print the most? Would it be equal since signed and unsigned would produce the same result, then if you have a negative like -1, when it gets assigned to int x it becomes 0xFF, and if you want to do -1 + (-1), if you do it the signed way to get -2 = 0xFE, and since the unsigned variables would be set to 0xFF, if you add them you would still get 0xFE. And the same holds true for 2 + (-3) or -2 + 3, in the end the hexadecimal values are identical. So in C is that what's looked at when it sees signedSum == unsignedSum? It doesnt care that one is actually a large number and the other is -2, as long at the 1's and 0's are the same?
Are there any values that would make this not true?
The examples you have given are incorrect in C. Also, converting between signed and unsigned types is not required to preserve bit patterns (the conversion is by value), although with some representations bit patterns are preserved.
There are circumstances where the result of operations will be the same, and circumstances where the result will differ.
If the (actual) sum of adding two ints would overflow an int
(i.e. value outside range that an int can represent) the result is
undefined behaviour. Anything can happen at that point (including
the program terminating abnormally) - subsequently converting to an unsigned doesn't change anything.
Converting an int with negative value to unsigned int uses modulo
arithmetic (modulo the maximum value that an unsigned can
represent, plus one). That is well defined by the standard, but
means -1 (type int) will convert to the maximum value that an
unsigned can represent (i.e. UINT_MAX, an implementation defined
value specified in <limits.h>).
Similarly, adding two variables of type unsigned int always uses
modulo arithmetic.
Because of things like this, your question "which would produce the most?" is meaningless.

I have used `unsigned char` type in order to give me data range up to 255, but not happen

I Have a simple code to convert from decimal to binary as follow
unsigned char number= 150, reminder=0;
while(number > 0){
printf("number=%d, ", number);
reminder = number % 2;
number /= 2;
printf("reminder=%d\n", reminder);
}
printf("\n");
the problem is when I input a decimal number greater than 127, gives me a binary number represent a negative number.
How gave me a negative number and I have used unsigned char not char only ?
(online example)
Note: I'm using visual studio 2010.
for printf use %u instead of %d
%d is for signed and %u is for unsigned number printing.
I think you need the following:
printf("reminder=%u\n", (unsigned int)reminder);
Does that work for you? For an explanation of why, see the dicussions on this question here.
basically a char is 8 bit long(1 BYTE) and it can hold -128 to 127 value for a signed char and 0 to 255 value for unsigned char ...and in any compiler whether it is 16 bit or 32 it only occupies 1 byte.......
now the story behind getting a -ve number is explained below....
since the range of char both signed and unsigned is shown above, whenever the compiler encounters value exceeded from the max, the compiler starts again from the beginning.
Ex: for signed char if value exceeds 127 it returns a -ve number i.e the starting range of signed char. for 128 it reutrns a -128. for 129 - (-127) etc..
same is for unsigned char...
sample pgm :
#include<stdio.h>
#include<conio.h>
int main()
{
char ch1 = 128;
unsigned char ch2 = 257;
printf("%d\n %d",ch1,ch2);
getch();
}
o/p : -128
1
Sample program 2 :
#include<stdio.h>
Void main()
{
unsigned char ch;
for(ch=0;ch<=255;ch++)
{
printf("%d-%c",ch,ch);
}
}
This program should print the ASCII value and the corresponding characters. But it wont. this program is an indefinite loop. The reason is that ch has been defined as a char. And char cannot take values bigger than +127. Hence when the value of cha is +127 and we perform ch++ It becomes -128 instead of +128. -128 is less than 255, hence the condition gets satisfied. Here onwards ch would take values like -127,-126,-----,-1,0,+1,+2,------,+127,-128,-127 etc.
Hope this helps..

Resources