How would I change this function to handle negative numbers? It correctly outputs everything but it does not make the leading bit 1 when negative. I can't do a negative check then simply force the first bit to be 1 because the amount of 0s between the leading bit and rest of the numbers will be off.
char* fromInt(int bin){
static char str[33];
str[1] = '\0';
int n;
for (n = 128; n > 0; n >>= 1){
if( (bin & n) == n){
strcat(str, "1");
}else{
strcat(str, "0");
}
}
return str;
}
I guess what you want is:
char* fromInt(int bin)
{
static char str[33];
str[0] = '0' + ((bin & 0x80000000) == 0x80000000);
str[1] = '\0';
for (int n = 0x40000000; n > 0; n >>= 1) {
if ((bin & n) == n)
strcat(str, "1");
else
strcat(str, "0");
}
return str;
}
The function has two steps. First is to determine the setting of sign bit (assuming that int object has 32 bits and it uses two's complement arithmetic):
(bin & 0x80000000) == 0x80000000
yields either 1 or 0. Because it's about the sign, It might have been written simply as:
'0' + (bin < 0)
The second step is to loop over remaining bits from position 30 to 0, like in the original code.
Here is an example program:
int main(void)
{
printf("%s\n", fromInt(0));
printf("%s\n", fromInt(1536));
printf("%s\n", fromInt(-1));
return 0;
}
This will output:
00000000000000000000000000000000
00000000000000000000011000000000
11111111111111111111111111111111
Related
I'm not able to get the right output when I do the following code. look at the comments for what I'm trying to print.
I did the code based on what I've been learning so far, but I'm still not getting the right output.
So any suggestions? What have I done, so I'm able to fix the problem.
When I print(A), I'm not getting 0100 0001, but it prints 49d or 49 sometimes
#include <stdio.h>
unsigned char getBit(unsigned char c, int n)
{
return ((c & (1 << n)) >> n);
}
unsigned char setBit(unsigned char c, int n)
{
c = c | (1 << n);
return c;
}
unsigned char clearBit(unsigned char c, int n)
{
c = c & (~(1 << n));
return c;
}
void printBits(unsigned char c)
{
printf("The bit of the character you inputed is %x \n", c);
}
int main(void)
{
unsigned char a = 'A';
printBits(a);
putchar('\n');
a = setBit(a, 2);
a = setBit(a, 3);
printBits(a); //should print 0100 0001, but it prints 49
putchar('\n');
a = clearBit(a, 2);
printBits(a);
putchar('\n');
}
Your current solution prints the value of c as a hexadecimal number using printf(). Since there is no printf format specifier to print a number in binary representation, we'll have to write our own solution.
#include <limits.h>
#include <stdio.h>
void printBits(byte c)
{
for (unsigned i = CHAR_BIT; i;) { // count from the with of a char
// in bits down to 1
putchar(c & 1 << --i // test the i-th bit (1-based)
? '1' // if true (different form 0) evaluates to '1'
: '0' // else evaluates to '0'
);
if (CHAR_BIT == 8 && i % 4 == 0) // if we use 8-bit-bytes and just
// finished printing the higher nibble
putchar(' '); // insert a seperator between the nibbles
}
}
... ftw!
No-nonsense version:
void printBits(byte c)
{
for (unsigned i = CHAR_BIT; i;) {
putchar(c & 1 << --i ? '1' : '0');
if (CHAR_BIT == 8 && !(i % 4))
putchar(' ');
}
}
`
unsigned char a = 'A';
printBits(a); // should print 0100 0001
putchar('\n');
a = setBit(a, 2);
a = setBit(a, 3);
printBits(a); // should print 0100 1101
putchar('\n');
a = clearBit(a, 2);
printBits(a); // should print 0100 1001
putchar('\n'
I'm building a function that, given an integer, reverses all 32 of its bits (including sign bit), converts that into a new integer, and returns it. I've almost finished it but I've run into two problems:
Part 1:
If I give it test(15); then
buffer = 11110000000000000000000000000000, which is indeed 15 with all the bits reversed.
but if I give it test(-15); then
buffer = 10001111111111111111111111111111, which is NOT right, it should be 10001000000000000000000000000001 (the 1 at the end is the sign bit). So for negative values, building my buffer string is going awry. Should I just change it to a positive integer, reverse the bits, and change the bit at the end to 1? Or is there some easier way of building this string?
Part 2:
"answer", the integer I'm returning that is supposed to represent these numbers, is never accurate. If I give it test(1500) answer = 185, when it should be 1000341504. What's the best way to turn a 32-bit binary number into an integer?
my code:
int test(int var){
printf("reversing %d:\n", var);
char buffer[32];
int i = 0;
int power = sizeof(var) * 8;
int answer = 0;
while(power > 0){
//check the lowest bit and put a 0 or 1 into the array
if((var & 1) == 1){
buffer[i] = '1';
i++;
}
else{
buffer[i] = '0';
i++;
}
//shift to the next bit
var>>= 1;
power--;
}
i++;
buffer[i] = '\0';
printf("\nbuffer = %s", buffer);
//loop through the array in reverse, building the number
while(i > 0){
if(buffer[i] == '0'){
i--;
}
else{
answer += (2 ^ (32 - i)); //here is where I try to add up answer
i--;
}
}
printf("\nanswer = %d \n\n\n\n", answer);
return 0;
}
The incorrect part of your conversion is:
answer += (2 ^ (32 - i))
2 ^ (32 - i)) is 2 XOR (32 - i), because ^ is the XOR-operator.
I'd do the conversion like this:
unsigned int answer = 0, pow=1;
for(int i = sizeof(buffer) - 1; i >= 0; --i)
{
int bit = buffer[i] - '0';
answer += bit * pow;
pow *= 2;
}
By doing it backwards (from 31 to 0), you don't have to use pow or create a
function that does 2 to the power of i. That would give you the integer value
of your binary interpretation, always positive. If you want to the integer value
of a 2-complement binary:
int answer = 0;
unsigned int pow=1;
for(int i = sizeof(buffer) - 1; i > 0; --i)
{
int bit = buffer[i] - '0';
answer += bit * pow;
pow *= 2;
}
if(buffer[0] == '1')
answer |= 0x80000000; // setting last bit
Or the more general solution (doesn't care if answer is signed or unsigned)
int answer = 0; // or unsigned int answer = 0;
size_t len = strlen(buffer);
for(int i = len - 1; i > 0; --i)
{
if(buffer[i] == '1')
answer |= 1 << len - 1 - i;
}
edit
I also found an error on your conversion to string:
char buffer[32];
...
i++;
buffer[i] = '\0';
The buffer hold 32 chars, one for each bit. There is no room left for the
0-terminating byte there, also with i++ you are overflowing the buffer, i
would be 33, so you are overflowing by 2.
If you are not going to treat buffer as a string (no strcpy, no strcmp,
no printf), then you don't have to store the terminating '\0'. Remove the
buffer[i] = '\0'; and that's it.
However you do print it as a string, so you would have to declare buffer as
char buffer[33];
and remove the i++ before buffer[i] = '\0';.
In that case, you would need to change the for loops as well, to
for(i = sizeof(buffer) - 2; i >= 0; --i)
and
for(i = sizeof(buffer) - 2; i > 0; --i)
or strlen(buffer) - 1 instead of sizeof(buffer) - 2 (in case you do the
convertion on another function and you pass the pointer to buffer.
I have tried to implement crc in c.My logic is not very good.What I have tried is to copy the message(msg) in a temp variable and at the end I have appended number of zeros 1 less than the number of bits in crc's divisor div.
for ex:
msg=11010011101100
div=1011
then temp becomes:
temp=11010011101100000
div= 10110000000000000
finding xor of temp and div and storing it in temp
gives temp=01100011101100000 counting number of zeros appearing before the first '1' of temp and shifting the characters of div right to that number and then repeating the same process until decimal value of temp becomes less than decimal value of div. Which gives the remainder.
My problem is when I append zeros at the end of temp it stores 0's along with some special characters like this:
temp=11010011101100000$#UFI#->Jp#|
and when I debugged I got error
Floating point:Stack Underflow
here is my code:
#include<stdio.h>
#include<conio.h>
#include<math.h>
#include<string.h>
void main() {
char msg[100],div[100],temp[100];
int i,j=0,k=0,l=0,msglen,divlen,newdivlen,ct=0,divdec=0,tempdec=0;
printf("Enter the message\n");
gets(msg);
printf("\nEnter the divisor\n");
gets(div);
msglen=strlen(msg);
divlen=strlen(div);
newdivlen=msglen+divlen-1;
strcpy(temp,msg);
for(i=msglen;i<newdivlen;i++)
temp[i]='0';
printf("\nModified Temp:");
printf("%s",temp);
for(i=divlen;i<newdivlen;i++)
div[i]='0';
printf("\nModified div:");
printf("%s",div);
for(i=newdivlen;i>0;i--)
divdec=divdec+div[i]*pow(2,j++);
for(i=newdivlen;i>0;i--)
tempdec=tempdec+temp[i]*pow(2,k++);
while(tempdec>divdec)
{
for(i=0;i<newdivlen;i++)
{
temp[i]=(temp[i]==div[i])?'0':'1';
while(temp[i]!='1')
ct++;
}
for(i=newdivlen+ct;i>ct;i--)
div[i]=div[i-ct];
for(i=0;i<ct;i++)
div[i]='0';
tempdec=0;
for(i=newdivlen;i>0;i--)
tempdec=tempdec+temp[i]*pow(2,l++);
}
printf("%s",temp);
getch();
}
and this part of the code :
for(i=newdivlen;i>0;i--)
divdec=divdec+div[i]*pow(2,i);
gives error Floating Point:Stack Underflow
The problem is that you wrote a 0 over the NUL terminator, and didn't put another NUL terminator on the string. So printf gets confused and prints garbage. Which is to say that this code
for(i=msglen;i<newdivlen;i++)
temp[i]='0';
printf("\nModified Temp:");
printf("%s",temp);
should be
for(i=msglen;i<newdivlen;i++)
temp[i]='0';
temp[i] = '\0'; // <--- NUL terminate the string
printf("\nModified Temp:");
printf("%s",temp);
You have to do this with integers
int CRC(unsigned int n);
int CRC_fast(unsigned int n);
void printbinary(unsigned int n);
unsigned int msb(register unsigned int n);
int main()
{
char buf[5];
strcpy(buf, "ABCD");
//convert string to number,
//this is like 1234 = 1*1000 + 2*100 + 3*10 + 4, but with hexadecimal
unsigned int n = buf[3] * 0x1000000 + buf[2] * 0x10000 + buf[1] * 0x100 + buf[3];
/*
- "ABCD" becomes just a number
- Any string of text can become a sequence of numbers
- you can work directly with numbers and bits
- shift the bits left and right using '<<' and '>>' operator
- use bitwise operators & | ^
- use basic math with numbers
*/
//finding CRC, from Wikipedia example:
n = 13548; // 11010011101100 in binary (14 bits long), 13548 in decimal
//padding by 3 bits: left shift by 3 bits:
n <<= 3; //11010011101100000 (now it's 17 bits long)
//17 is "sort of" the length of integer, can be obtained from 1 + most significant bit of n
int m = msb(n) + 1;
printf("len(%d) = %d\n", n, m);
int divisor = 11; //1011 in binary (4 bits)
divisor <<= (17 - 4);
//lets see the bits:
printbinary(n);
printbinary(divisor);
unsigned int result = n ^ divisor;// XOR operator
printbinary(result);
//put this in function:
n = CRC(13548);
n = CRC_fast(13548);
return 0;
}
void printbinary(unsigned int n)
{
char buf[33];
memset(buf, 0, 33);
unsigned int mask = 1 << 31;
//result in binary: 1 followed by 31 zero
for (int i = 0; i < 32; i++)
{
buf[i] = (n & mask) ? '1' : '0';
//shift the mask by 1 bit to the right
mask >>= 1;
/*
mask will be shifted like this:
100000... first
010000... second
001000... third
*/
}
printf("%s\n", buf);
}
//find most significant bit
unsigned int msb(register unsigned int n)
{
unsigned i = 0;
while (n >>= 1)
i++;
return i;
}
int CRC(unsigned int n)
{
printf("\nCRC(%d)\n", n);
unsigned int polynomial = 11;
unsigned int plen = msb(polynomial);
unsigned int divisor;
n <<= 3;
for (;;)
{
int shift = msb(n) - plen;
if (shift < 0) break;
divisor = polynomial << shift;
printbinary(n);
printbinary(divisor);
printf("-------------------------------\n");
n ^= divisor;
printbinary(n);
printf("\n");
}
printf("result: %d\n\n", n);
return n;
}
int CRC_fast(unsigned int n)
{
printf("\nCRC_fast(%d)\n", n);
unsigned int polynomial = 11;
unsigned int plen = msb(polynomial);
unsigned int divisor;
n <<= 3;
for (;;)
{
int shift = msb(n) - plen;
if (shift < 0) break;
n ^= (polynomial << shift);
}
printf("result: %d\n\n", n);
return n;
}
Previous problems with string method:
This is infinite loop:
while (temp[i] != '1')
{
ct++;
}
Previous problems with string method:
This one is too confusing:
for (i = newdivlen + ct; i > ct; i--)
div[i] = div[i - ct];
I don't know what ct is. The for loops are all going backward, this makes the code faster sometimes (maybe 1 nanosecond faster), but it makes it very confusing.
There is another while loop,
while (tempdec > divdec)
{
//...
}
This may go on forever if you don't get the expected result. It makes it very hard to debug the code.
I have been trying for the past several hours to convert a negative binary with the first bit as 1 to a decimal. The twos complement conversion seems to be impossible but I believe there has to be some easier way to do this because this is just the beginning of a beginner class in C.
int power;
int count = 0;
int length = strlen(value);
int result = 0;
int negResult = 0;
int i = length - 1;
int j;
if (value[0] == '1') {
for (; i >= 0; i--) {
if (value[i] == '1')
result += 1;
result << 1;
}
printf("%d\n", result);
result = ~result;
result += 1;
printf("%d\n", result);
for (j = 8; j > 0; j--) {
if (result << (8-j) == 1) {
power = (int) pow(2,count);
negResult += power;
}
count++;
}
printf("-%d\n", negResult);
}
else {
for (; i >= 0; i--) {
if (value[i] == '1') {
power = (int) pow(2,count);
result = result + power;
}
count++;
}
printf("%d\n", result);
}
}
I pass it:
binary_to_decimal("10011011");
and I get 5 then -5 and then -0 for each printf.
I did not include the code that actually converts it to a decimal since for positive binaries it works fine and I believe once the twos complement works it should work for negative binaries as well.
You may not be clear about what temp += '0' is doing. It's not making a string, rather it's offsetting an uninitialized pointer and is the cause of the segfault when you come to actually use it as in temp2[j]. To work with strings like I think you're wanting to, check out strcat().
I would junk this and start over. Don't manipulate chars in strings, just convert the string to a binary. Write some code to walk the input string from the first character towards the last. Keep a result integer for your answer, initially 0. As you walk through the string, shift result << 1, and then if you see a char '1', add a number 1 to result. If you see a '0' in the string don't add anything, but in either case do the left shift first.
This will get you a binary of however many bits you have. For negative numbers (topmost (first) bit = '1') you will need to sign extend by OR-ing '1' into all the bits above the sign bit, bitwise-invert the result and add 1. Check this on paper to see how it works, and be aware the input string can't be too long. Good luck with the class.
int length = strlen(value);
unsigned int result = 0;
unsigned int signExtend;
unsigned int negResult = 0;
// assemble incoming chars as bits in an unsigned int
for (int i=0;i<length;i++) {
result = result << 1;
if (value[i] == '1')
result += 1;
}
printf("0x%x, %d\n", result, result); // see it is a hex number and a decimal
// if negative, convert to positive number
if (value[0] == '1') {
// first, sign-extend
signExtend = (1 << (length-1));
signExtend -= 1;
signExtend = ~signExtend;
result |= signExtend;
printf("signExtend mask = 0x%x, sign-extended number = %x\n", signExtend, result);
// then, two's complement
negResult = ~result;
negResult += 1;
// show the result with the '-' sign explicitly added:
printf("result is -%d\n", negResult);
// but actually, once you have sign extended,
// you can cast the result as signed and just print it:
printf("result as signed int = %d\n", (int)result);
} else {
// positive result, just print it
printf("result is %d\n", result);
}
here's how I would do it
int btd(char *str)
{
int i , l = strlen(str) , neg = 0;
int res = 0;
for(i = 0 ; i < l ; i++)
{
if(!i)
{
if(str[i] == '1');
neg++;
continue;
}
if(str[i] == '1')
{
res <<= 1;
res |= 1;
}
else
res <<= 1;
}
if(neg)
res *= -1;
return res;
}
I feel like I am nearing an end on this assignment, but do not understand why it only works correctly every other time. If I enter "FFFFFFFF" my program prints out:
0xFFFFFFFF
signBit 1, expBits 255, fractBits 0x007FFFFF
QNaN
but if I enter "FFFFFFFF" again my program prints out:
0xFFFFFFFF
my program will not print out the correct output every time but yet every other time.
Is there anyone who can help me identify where the error occurs in my code?
Any help is greatly appreciated!
Thanks!
// do not change this code except in the following ways:
// * write code for the following functions:
// * bigOrSmallEndian()
// * getNextHexInt()
// * printLinesForNumber()
// * change studentName by changing "I. Forgot" to your actual name
#include <stdio.h>
#include <stdlib.h>
static char *studentName = "Tenzin Shakya";
// report whether machine is big or small endian
void bigOrSmallEndian()
{
int num = 1;
if(*(char *)&num == 1)
{
printf("\nbyte order: little-endian\n\n");
}
else
{
printf("\nbyte order: big-endian\n\n");
}
}
// get next int (entered in hex) using scanf()
// returns 1 (success) or 0 (failure)
// if call succeeded, return int value via i pointer
int getNextHexInt(int *i)
{
// replace this code with the call to scanf()
//*i = 0;
//return 1;
scanf ("%x", i);
return 1;
}
// print requested data for the given number
void printNumberData(int i)
{
//printf("%x %0#10x\n",i,*(int *)&i);
int tru_exp =0;
//int stored_exp;
int negative;
int exponent;
int mantissa;
printf("\n>");
scanf("%x", &i);
printf("\n0x%08X",i);
negative = !!(i & 0x80000000);
exponent = (i & 0x7f800000) >> 23;
mantissa = (i & 0x007FFFFF);
printf("\nsignBit %d, ", negative);
printf("expbits %d, ", exponent);
printf("fractbits 0x%08X", mantissa);
// "%#010x, ", mantissa);
if(exponent == 0)
{
if(mantissa != 0)
{
printf("\ndenormalized ");
}
}
else{
printf("\nnormalized: ");
tru_exp = exponent - 127;
printf("exp = %d", tru_exp);
}
if(exponent == 0 && mantissa == 0 && negative == 1)
{
printf("\n-zero");
}
if(exponent ==0 && mantissa == 0 && negative == 0)
{
printf("\n+zero");
}
if(exponent == 255 && mantissa != 0 && negative == 1)
{
printf("\nQNaN");
}
if(exponent == 255 && mantissa != 0 && negative == 0)
{
printf("\nSNaN");
}
if(exponent == 0xff && mantissa == 0 && negative == 1)
{
printf("\n-infinity");
}
if(exponent == 0xff && mantissa == 0 && negative == 0)
{
printf("\n+infinity");
}
printf("\n");
while(i != 0)
break;
}
// do not change this function in any way
int main(int argc, char **argv)
{
int i; // number currently being analyzed
int nValues; // number of values successfully parsed by scanf
printf("CS201 - A01p - %s\n\n", studentName);
bigOrSmallEndian();
for (;;) {
if (argc == 1) // allow grading script to control ...
printf("> "); // ... whether prompt character is printed
nValues = getNextHexInt(&i);
printf("0x%08X\n", i);
if (! nValues) { // encountered bad input
printf("bad input\n");
while (getchar() != '\n') ; // flush bad line from input buffer
continue;
}
printNumberData(i);
if (i == 0)
break;
}
printf("\n");
return 0;
}
You are inputting the user's number in getNextHexInt, but printNumberData asks for the input again with another scanf. You don't need the second scanf because the input i is already set to the user's input from getNextHexInt.
here's the code for doing that
float myFloat;
int myInt;
memcpy(&myInt, &myFloat, 4);
int signBit = ((1 << 31) & myInt) >> 31;
printf("%i\n", signBit)
I typed it up in a rush, hopefully it works, ill check it in a sec
Heres a program, but it displays -1 for some reason for sign
#include <string.h>
#include <stdio.h>
int main()
{
float a = 1337;
int* b = (int*)&a;
int signbit = ((1 << 31) & *b) >> 31;
printf("%i\n", signbit);
a *= -1;
signbit = ((1 << 31) & *b) >> 31;
printf("%i\n", signbit);
return 0;
}