Converting a negative decimal to binary - c

So, I made this code.
Basically, takes in the number, then if negative, converts it to positive, calculates its binary and then its one complement and then adds 1.
#include <stdio.h>
int main (void)
{
int bin[8]={0};
int sum[8];
int orig,num,i=0,j;
int addn[8] = {0,0,0,0,0,0,0,1};
int carry = 0;
printf("Please enter the number\n");
scanf("%d",&num);
if ( num < 0 )
{
orig = num;
num = -num;
}
while (num!= 0)
{
bin[8-i-1] = num%2;
num = num/2;
i++;
}
for ( j = 0; j < 8; j++ )
{
printf("%d",bin[j]);
}
printf("\n");
if ( orig < 0 )
{
for ( i = 0; i < 8; i++ )
{
if (bin[i] == 0)
bin[i] = 1;
else
bin[i] = 0;
}
for ( i = 0; i < 8; i++ )
{
sum[i] = ((bin[i]^addn[i])^carry);
carry = ((bin[i] & addn[i])| (bin[i] & carry) | (addn[i] & carry) );
}
printf("The 2's complement of the number is \n");
printf("%d",carry);
for ( i = 0; i < 8; i++ )
{
printf("%d",sum[i]);
}
printf("\n");
}
return 0;
}
When I enter the value as 4, it correctly displays its binary value. However, it shows the its 2 compliment as 111111010 ( This is with carry ). Why is this happening? The 2's compliment form of -4 should be different.
Also, is there any other method of converting a negative number to its 2's compliment form?

If you check the 1's complement you'll find that's correct.
The slip is, you're storing the MSB in num[0] and the LSB in num[7], so when you're adding, you need to begin at the 7 end, not the 0 end. Putting (8-i-1) in all the addition part, produces something more like :
./a.out
Please enter the number
-4
00000100
The 1's complement of the number is
11111011
The 2's complement of the number is
011111001
That looks almost right at the low end, but the sign bit looks wrong, because you suddenly are outputting 9 bits, may be you intend to show the overflowing carry? I'm a bit confused about your output intentions and I haven't even examined that part of the source carefully.
I won't post the fixed source yet, you should try to learn to debug it yourself by putting in the extra printf's and reasoning about how you input the number initially.
Thanks for the nifty example program, though it could do with some serious refactoring for clarity. Is it a study exercise? If so you really SHOULD learn to find errors yourself.
Here goes with the corrections I intended but didn't quite input correctly first time :)
So to check the 1's complement was correct :
printf("The 1's complement of the number is \n");
for ( j = 0; j < 8; j++ )
{
printf("%d",bin[j]);
}
printf("\n");
Before starting the add. Then to fix :
for ( i = 0; i < 8; i++ )
{
sum[8-i-1] = ((bin[8-i-1]^addn[8-i-1])^carry);
carry = ((bin[8-i-1] & addn[8-i-1])| (bin[8-i-1] & carry) | (addn[8-i-1] & carry) );
}
Originally I had typo ((bin[i-i-1]^addn but I didn't really care about exact results as I knew I had found what was wrong and could explain where the fault lay.

Related

why this code isn't converting decimals to binary from decimals 0 to 31

So I was trying to convert a decimal number to binary using c. In this code every thing seems to be working well. Also this code does work for decimals from 32, 33 and go on. But this code doesn't work for decimals from 0 to 31. What's the bug in here.
#include <stdio.h>
#include <math.h>
int main(void)
{
int decimal;
printf("Enter the decimal value: ");
scanf("%i", &decimal);
int n, remainder;
int i, j, k;
for (int i = 0; i < decimal; i++)
{
if (pow(2, i) <= decimal)
{
n = i;
}
}
char index[n];
int quotient[n];
quotient[0] = decimal;
for (i = 0; i <= n; i++)
{
quotient[i + 1] = quotient[i] / 2;
remainder = quotient[i] % 2;
if (remainder == 1)
{
index[i] = '1';
}
else
{
index[i] = '0';
}
}
for (int k = n; k >= 0; k--)
{
printf("%c", index[k]);
}
return 0;
}
The number returned by scanf() is a bit pattern (binary) representation of the base10 value you enter.
You've got the right idea (trying to 'pick apart' those bits), but the method used is dubious and confusing.
Below is a loop of some familiar values being converted to strings of 1's and 0's.
Consider what it is doing at each step...
int main() {
for( int i = 253; i <= 258; i++ ) {
printf( "Decimal %d: ", i );
unsigned int bitmask = 0;
bitmask = ~bitmask;
bitmask &= ~(bitmask >> 1); // High bitmask ready
// skip over leading 0's (optional)
while( bitmask && (bitmask & i) == 0 ) bitmask >>= 1;
// loop using bitmask to output 1/0, then shift mask
do {
putchar( (bitmask & i) ? '1' : '0' );
} while( (bitmask >>= 1) != 0 );
putchar( '\n' );
}
return 0;
}
Output:
Decimal 253: 11111101
Decimal 254: 11111110
Decimal 255: 11111111
Decimal 256: 100000000
Decimal 257: 100000001
Decimal 258: 100000010
I don't like this, but you seem to want to use pow() to find the highest set bit in the incoming integer. Perhaps this will lead you to the solution you are looking for.
int main() {
int n = 0;
// generate a series of numbers as input
for( int decimal = 1; decimal < 1000*1000*1000; decimal = decimal * 2 + 1 ) {
// Limited of 32 bit integers INCLUDING sign bit
for (int i = 0; i < 31; i++) {
int guess = (int)pow( 2, i ); // make a guess with this value
printf( "Guess %d\n", guess );
if( guess > decimal ) { // guess now encompasses set bits
n = i; // Found what is needed.
break;
}
}
printf( "decimal input = %d: examining %d bits\n", decimal, n );
getchar();
}
return 0;
}
Here's one sample of the output of the above.
Guess 1
Guess 2
Guess 4
Guess 8
Guess 16
Guess 32
Guess 64
decimal input = 63: examining 6 bits
Note: this sort of thing will only work for positive values. It'll probably blow up if you want the bit pattern of a negative integer.
And, because you want to store an array of quotient, you need to dimension it to have +1 elements to avoid stepping out of bounds as you peel-off each bit through division...

Quick way to turn a binary array into a decimal string

I have a binary number, stored in an array of bytes (unsigned chars), and want to turn it into a decimal string.
The "obvious" approach that i found online was, to iterate over the array, add everything up while keeping track of the base and then converting it into a string but this doesn't work for me because the whole number doesn't fit into any common datatype and therefor cannot be added up in one go.
typedef unsigned char byte;
typedef struct Bin {
int size;
byte *ptrToVal;
} Bin;
void asDecString(Bin* this) {
signed int n = 0;
for(int i = 0; i < this->size; i++) {
n += this->ptrToVal[i] << (i * 8);
printf("%u\t%u\t%u\n", this->ptrToVal[i], n, i);
}
printf("%u\n", n);
}
The second, slow approach is to store the number in a string and multiply the digits in the string.
I'm looking for a quick way to implement this in c, but because I'm completely new to the language I don't know the features that well.
Out of curiosity and interest, here's my implementation of the algorithm found at:
https://my.eng.utah.edu/~nmcdonal/Tutorials/BCDTutorial/BCDConversion.html
It outputs intermediary values as each bit is processed. The verbose block can be moved out of the loop after testing.
Try it with one or two 'hex' bytes to begin with.
#include <stdio.h>
typedef unsigned char binByte;
void toBCD( binByte *p, int size ) {
const int decSize = 50; // Arbitrary limit of 10^49.
binByte decDgt[ decSize ]; // decimal digits as binary 'nibbles'.
int curPow10 = 0;
memset( decDgt, 0, sizeof(decDgt) );
for( int i = 0; i < size; i++ ) {
binByte oneByte = p[ i ]; // Initial one byte value
for( binByte bit = 0x80; bit > 0; bit >>= 1 ) {
for( int ii = 0; ii <= curPow10; ii++ )
if( decDgt[ ii ] >= 5 ) // Algorithm step
decDgt[ ii ] += 3;
for( ii = curPow10; ii >= 0; ii-- ) {
decDgt[ ii ] <<= 1;
if( decDgt[ ii ] & 0x10 ) { // Carry high bit?
decDgt[ ii + 1 ] |= 0x1;
if( ii == curPow10 ) // new power of 10?
curPow10++;
}
decDgt[ ii ] &= 0xF; // dealing in 'nibbles'
}
decDgt[ 0 ] |= ( (oneByte & bit) != 0 ); // truth value 0 or 1
printf( "Bottom: " );
for( ii = curPow10; ii >= 0; ii-- )
putchar( decDgt[ ii ] + '0' );
putchar( '\n' );
}
}
}
void main( void ) {
binByte x[] = { 0x01, 0xFF, 0xFF, 0xFF, 0xFF };
toBCD( x, sizeof(x) );
}
For large integers; you want to break them into "small enough integers", then convert the "small enough integers" into digits.
For example, lets say you have the number 1234567890. By doing next_piece = number / 100; number = number % 100; you could split it into pieces that fit in one byte, then print the smaller pieces 12, 34, 56, 78, 90 (with nothing between them and leading zeros to ensure the piece 03 doesn't get printed as 3) so that it looks like a single larger number.
In the same way you could split it into pieces that fit in a 32-bit unsigned integer; so that each piece is from 0 to 1000000000, by doing something like next_piece = number / 1000000000; number = number % 1000000000;. For example, the number 11223344556677889900112233445566778899 could be split into 11, 223344556, 677889900, 112233445, 566778899 and then printed (with leading zeros, etc).
Of course for big integers you'd need to implement a "divide by 1000000000" that works with your data structure, that returns a uint32_t (the remainder or the next piece) and the original value divided by 1000000000.
This is where things get messy. Using an array of bytes is slow, and signed numbers are painful. To fix that you'd want something more like:
#include <stdint.h>
typedef struct AlternativeBin {
int signFlag;
int size;
uint32_t *ptrToVal;
} AlternativeBin;
It wouldn't be hard to convert from your original format into this alternative format (if you can't just use this alternative format for everything).
The division loop would look something like (untested):
// WARNING: Destructive (the input value is used to return the quotient)
uint32_t getNextPiece(AlternativeBin * value) {
uint64_t temp = 0;
int i;
// Do the division
for(i = value->size - 1; i >= 0; i--) {
temp = (temp << 32) | value->ptrToVal[i];
value->ptrToVal[i] = temp / 1000000000ULL;
temp = temp % 1000000000ULL;
}
// Reduce the size of the array to improve performance next time
while( (value->size > 0) && (value->ptrToVal[value->size - 1] == 0) ) {
value->size--;
}
return temp;
}
..which means the "printing loop" (using recursion to reverse the order of pieces) might look like (untested):
#include <stdio.h>
#include <inttypes.h>
// WARNING: Recursive and destructive (the input value is destroyed)
void printPieces(AlternativeBin * value) {
uint32_t piece;
piece = getNextPiece(value);
if( !value_became_zero(value) ) {
printPieces(value);
printf("%09" PRIu32, piece); // Print it with leading zeros
} else {
printf("%" PRIu32, piece); // No leading zeros on first piece printed
}
}
The other minor inconvenience is that you'll want to print a '-' at the start if the value is negative (untested):
// WARNING: Destructive (the input value is destroyed)
void printValue(AlternativeBin * value) {
if(value->signFlag) {
printf("-");
}
printPieces(value);
}
If you wanted you could also create a copy of the original data here (get rid of the WARNING: Destructive comment by destroying a copy and leaving the original unmodified); and convert from your original structure (bytes) into the alternative structure (with uint32_t).
Note that it would be possible to do all of this with bytes (something like your original structure) using a divisor of 100 (instead of 1000000000). It'd just be a lot slower because the expensive getNextPiece() function will need to be called about 4.5 as many times.

Binary decimal conversion with arrays

Do you have a simple idea of how we go from a binary number to a decimal number in C without doing any divisions (because I can have very big numbers), maybe only with masks (&, |, << or >>) .
I have a table like this:
tab[20] = {1,0,0,1,0,0,0,1,1,0,0,1,0,0,0,1,1,1,0,1};
and I would like this :
tab[6] = {5,9,6,2,5,3};
Is this something that can be done ? Thank you for your help
idea of how we go from a binary number to a decimal number (can have very big numbers)
For each binary digit, scale the decimal destination by 2 and add the digit.
Pseudo code
some_integer_type tab2[] = {1,0,0,1,0,0,0,1,1,0,0,1,0,0,0,1,1,1,0,1};
some_integer_type tab10[big_enough];
zero fill tab10[]
for (each i element in tab2[] starting with index 0) {
// scale tab10[] by 2 and add tab2[]
carry = tab2[i]
for (each j element in tab10[] starting with the last index) {
sum = (tab10[j] << 1) | carry;
if (sum >= 10) {
sum -= 10;
carry = 1;
} else {
carry = 0;
}
tab10[i] = sum;
}
}
print tab10[]
To do >=, -= 10 with only &, |, << or >>, create helper functions: divide and conquer.
No division and up to 64 bit. This is "big". The bin-to-dec is done with sprintf(). That digit-string can then be converted to an array of integers like your tab[6]
char bittab[64] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0};
long num = 0, dupl = 1;
int i;
for (i = 0; i < sizeof bittab; i++) {
num += dupl * bittab[i];
dupl *= 2;
}
char decstring[30];
sprintf(decstring, "%ld\n", num);
for (i = 0; i < strlen(decstring); i++)
printf("%d\n", decstring[i] - '0');
The output is:
3
2
7
6
7
-38
This can be written into a dectab[] array, excluding the null terminator byte.
(I made the bits ascending to leave the size open.)

Test result fails for my code of Inspect Bits function

Below code is for a test sample given in https://www.testdome.com/for-developers/solve-question/9780
The question is: Implement the inspect_bits function that checks if given number contains 2 or more consecutive ones in its binary representation. If it does, the function should return 1. Otherwise, it should return 0.
For example, inspect_bits(13) should return 1 as it contains 2 consecutive ones in its binary representation (1101).
My code is:
#include <stdlib.h>
#include <stdio.h>
int inspect_bits(unsigned int number)
{
unsigned int ref = 1;
int comp;
for (int i = 0; i< sizeof(number) * 8; i++)
{
int a = number& (ref << i);
printf("%d: a is %d\n", i, a);
int b = number& (ref << (i + 1));
printf("%d: b is %d\n", i, b);
if ((a != 0) && (b != 0))
{
return 1;
}
}
return 0;
}
#ifndef RunTests
int main()
{
printf("%d", inspect_bits(13));
}
#endif
The result seems ok, but the system tells:
Various numbers: Wrong answer
Can you help to modify my code?
Regards
To be honest, I think it's an issue with the test site itself. Your code returns the proper results for each test case given to it, and I even modified the code as such:
int inspect_bits(unsigned int number)
{
for (int i = 0; i < sizeof(number) * 8; ++i) {
if (((number & (1 << i)) != 0) && ((number & (1 << (i + 1))) != 0)) {
return 1;
}
}
return 0;
}
The test cases return 1 where there are 2 binary values together and works for 3 and above; however, running this code on the test site and it gives the error that the Various Numbers test fails.
Interestingly, using this code:
int inspect_bits(unsigned int number)
{
while (number >= 3) {
if ((number & 3) == 3) { return 1; }
number >>= 1;
}
return 0;
}
Which does basically the same thing, only using bit-shifting on a single number, and the test passes 100% ..
You could submit an e-mail explaining the error; but beyond that, I'm not sure what else it could be.
Hope that helps.
int flag = 0;
int inspect_bits(unsigned int number)
{
int *arr;
int i = 0;
number = convert(number);
while(number)
{
arr[i] = number % 10;
number /= 10;
i++;
}
for(int j = 0; j < i-1; j++)
{
if(arr[j] == arr[j+1])
{
flag = 1;
return flag;
}
}
return flag;
}
int convert (int num)
{
if(num == 0)
{
return 0;
}
else
{
return (num % 2 + 10 * convert(num / 2));
}
}
This is what I did and it said Various Words: Wrong Answer. It appears to be an issue with the test site. Some other questions on their site evaluates questions incorrectly. The ones that I've come across are all C programs. C++ works fine in my experience.
By my experience in testdome almost any exercise right solution has to do with efficiency of the algorithm
This code worked for me:
#include <stdlib.h>
#include <stdio.h>
int inspect_bits( unsigned int number ) {
do {
if( ( number&3 )==3 ) return 1;
} while( number>>=1 );
return 0;
}
#ifndef RunTests
int main () {
printf( "%d", inspect_bits( 13 ) );
}
#endif
In the code you posted, the for loop checks all the bits from the function's input argument 'number'. That's not enough efficient.
The point is that we don't have to wait until the complete number has been completely right shifted.
They say, we must check if there are 2 or more consecutive ones in its binary representation, in other words, function returns 1 if a minimum of 2 consecutive bits with value 1 are found, and the fewer value with 2 consecutive ones is a decimal 3 ( 3 = 0b00000011 ).
So we are able to check it comparing the number with 3 using an AND gate, and right shift to 'number' until it happens.
Let's take a different number than the example's one:
221 = 0b11011101 we just only need to compare 3 times and shift it 2 times.
0b11011101 (221)
& 0b00000011 ( 3)
------------------
= 0b00000001 ( 1)
0b11011101(221) >> 1 = 0b01101110(110)
0b01101110 (110)
& 0b00000011 ( 3)
------------------
= 0b00000010 ( 2)
0b01101110(110) >> 1 = 0b00110111(55)
0b00110111 (55)
& 0b00000011 ( 3)
------------------
= 0b00000011 ( 3) ----> FOUND! return 1

A binary to decimal program

I was practicing basic programs of C and tried to do a binary to decimal conversion.
Below is the code I tried but it did not produce correct results. I couldn't understand where my logic goes wrong.
/* binary to decimal */
#include<stdio.h>
int main()
{
int a,i,p,sum=0;
printf("enter binary number\n");
scanf("%u",&a);
for(i = 0 ; i < 5; i++) /* Taking only 5 digits in binary */
{
if((a & 1<<i))
{
p = 1<<i;
sum = sum +p;
}
}
printf("%d\n",sum);
return 0;
}
I entered 1001 and was expecting 9 to be the output, but output was 1001?
scanf("%u",&a); will read a decimal number. Therefore when you enter 1001 it will be 0011 1110 1001 in binary and after you convert this number back to decimal it becomes 100110. You should read it as a string to preserve the binary form
And then the code you wrote only checks the lower 5 bits of the input value. If you enter 1001 it will output 9 as "expected" because the lower bits of 1001 is 01001 which is accidentally the same for 9. The output is not 1001 as you described. That means the code above is not the original code you ran. If you enter another number the result will be different. For example entering 36 will print 4 on the output
Reason is very simple, variable 'a' is of type int hence when you provide the input as 1001 it becomes a integer of 1001 not a binary for the compiler, so you will not get the proper result, don't use shift operator, try some thing similar as suggested by others
This should help you:
#include<stdio.h>
int main()
{
int a,i,p,sum=0;
int temp;
printf("enter binary number\n");
scanf("%d",&a);
for(i = 0 ; i<5; i++) /* Taking only 5 digits in binary */
{
temp=a % 10;
a = a/10;
p = temp<<i;
sum = sum +p;
}
printf("%d\n",sum);
return 0;
}
You would do better to take the input as a string, and starting from the end of that string add the place values for the 1 digits.
%u interprets a decimal string as an integer, you are then trying to interpret the decimal representation of the resultant integer value as binary. Not only is that confusing and somewhat irrational, it will limit you to 10 binary digits.
Consider this:
/* binary to integer */
#include <stdio.h>
#include <string.h>
int main()
{
int pv = 1 ;
int value = 0 ;
char bin[33] ;
printf("Enter binary number: ");
scanf("%32s", bin ) ;
for( int i = strlen( bin ) - 1; i >= 0; i-- )
{
if( bin[i] == '1' )
{
value += pv ;
}
pv *= 2 ;
}
printf( "%d\n", value ) ;
return 0 ;
}
Note also that what is happening here is not a conversion to decimal, but rather conversion to integer. All values are stored internally in binary, it is only decimal if you choose to output a decimal string representation of the integer value.
A potentially more efficient version of the above that exploits the internal binary representation of integers is:
/* binary to integer */
#include <stdio.h>
#include <string.h>
int main()
{
int pv = 1 ;
int value = 0 ;
char bin[33] ;
printf("Enter binary number: ");
scanf("%32s", bin ) ;
for( int i = strlen( bin ) - 1; i >= 0; i-- )
{
if( bin[i] == '1' )
{
value |= pv ;
}
pv <<= 1 ; ;
}
printf( "%d\n", value ) ;
return 0 ;
}
These lines are wrong (I think..):
p = 1<<i;
sum = sum +p;
In order to comput the decimal value you have to do this:
p= pow(2,i);
sum = sum+p;
You need to raise 2 to the power i.
See this link for a good example code:
http://www.daniweb.com/software-development/c/threads/307756/binary-to-decimal-conversion-in-c
This code can be used in C++:
string str = "1001";
int temp = 0;
for(int c=0;c<str.length();c++){
int v = atoi( str.substr(c,1).c_str() );
temp=temp+(v*(pow (2, str.length()-c-1)));
}
cout << temp;

Resources