C program to find two's compliment - c

I came across a C code in a book to find the two's complement of a binary number. I wasn't familiar with the concept of one's and two's complement of a binary number so I did a thorough research and now understand a fair bit about the same. But I still have a few doubts about how the code works. The code is as follows (the comments were not there in the original code and have been added by me so that I could be corrected if it's wrong)-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main()
{
char a[16]; /*declaring an array to hold the binary number string*/
int i, j, k, len; /*len is the length of the string*/
printf ("Enter a binary number: ");
gets (a); /*reads the input string*/
len= strlen(a); /*calculates length of string*/
for (k=0; a[k]!='\0';k++) /*to check if its a valid binary number or not*/
{
if (a[k] != '0' && a[k]!='1')
{
printf ("\nIncorrect Binary format...this program will quit");
exit(0);
}
}
for (i=len-1; a[i]!='1'; i--) /* An empty for loop*/
;
for (j=i-1; j>=0; j--) /*checks from right to left if the bit is 0 or 1*/
{
if (a[j]=='1')
a[j]= '0'; /*if the bit is 1, its converted to 0*/
else
a[j]= '1'; /*if the bit is 0, its converted to 1*/
}
printf ("\n2's compliment = %s", a);
}
The code works absolutely fine, but I have doubts how.
First, I don't exactly understand what the empty for loop does. Does it counts till we encounter the first zero from the right side?
Second, in the third and last for loop, we just flip the value of each bit from 1 to 0 and from 0 to 1. But we do that for the one's complement, not the two's complement, right? We need to add 1 to the one's complement to find two's complement. The code dosen't seems to be doing that anywhere. How does it works then?
Kindly clearify, thanks in advance.

First, I don't exactly understand what the empty for loop does.
It is to find the rightmost 1 and assigns it to i.
Second, in the third and last for loop, we just flip the value of each
bit from 1 to 0 and from 0 to 1.
It is to flip all bits starting index i-1.
I have learnt the trick in my microprocessors course. It is that start read bits from right to left until see first bit which is 1. Don't flip it. After that, flip all bits.
Let's try, 10110 -> 01010
Start from right.
Read 0, it's not 1. Go ahead,
Read 1, yes, we get first bit which is 1. Don't flip it.
Read 1, flip it. Now it is 0.
Read 0, flip it. Now it is 1.
Read 1, flip it. Now it is 0.
We get 01010
The logic of the program is exactly what I mention.

Normally to compute the two's complement, we change all the 1's to 0's and all the 0's to 1, and then add 1.
Let's look at the two's complement of 172, or binary 10101100:
10101100
01010011 /* change all 0's to 1's and 1's to 0's */
01010100 /* add one */
Notice that when we added 1, we changed some of the 1's back to 0's. In fact, everything that had been a 0 at the right edge of the original number stayed 0. And the rightmost 1 in the original number stayed 1. And it was only the 1's and 0's to the left of the rightmost 1 that actually got swapped.
And that's what the mystery loop in the original program does. It scans from the right, skipping over 0's until it finds the first 1, and it's only the digits to the left of that point that it actually swaps. The variable i ends up holding the position of the rightmost 1, and then the next loop, the one that actually does the swapping, starts at j = i - 1.
One more thing: Sorry to nag about this, and you may know it already, but you really shouldn't use the gets() function, not even in a little test program. It's a truly horrid, dangerous function.

Related

Printing the binary representation of an unsigned char backwards?

How exactly does this code work? I'm confused about the first for loop since binary starts at 0 and as long as it is not equal to the binary representation of the char it will increase, so then binary is 1 and so on?
unsigned char c;
int binary;
scanf("%c", &c);
getchar();
printf("The decimal representation is: %d\n", c);
for (binary = 0; (1<<binary)<=c; binary++){ // moving to the left
} // until binary code matches c
printf("The backwards binary representation is: ");
for (int i=0; i<binary; i++){ // since we know the size
printf("%d", ((c>>i)&1)); // 1s and 0s are shifted to right
}
printf("\n");
return 0;
This:
for (binary = 0; (1<<binary)<=c; binary++)
simply counts how many significant bits are in the integer "c".
For instance, if "c" is 0101100 in binary, the most significant bit is the 6th from the right, and "binary" would be set to 6.
If "c" is 01 in binary, the most significant bit is the first from the right, and "binary" would be set to 1.
The biggest problem with this code is its almost useless comments.
If there must be comments, replace this:
/* moving to the left until binary code matches c */
with this:
/* Count number of significant bits.*/
Comments should say why the code is there, not describe how it works.
Comments like this don't serve any purpose:
/* since we know the size 1s and 0s are shift to right */
The second biggest problem is the variable names. "binary" is misleading. Call it "number_of_significant_bits" instead and the code almost doesn't need any comments.

bit comparison in loop on AVRs

I'm learning about bit logic in C on AVRs and I have a problem.
I want to compare an "i" bit (from the right) from int8_t variable and if it is 1, then do the next instruction, but it doesn't work. Here's what I write:
if (variable & (1<<i)==(1<<i)) instruction;
In example for following data:
uint8_t dot=0101;
PORTC=1;
for (int i=0; i<4; i++)
{
PORTB = fourDigit[i];
if (dot & (1<<i)==(1<<i)) PORTB--;
PORTC<<=1;
}
The dot (as it is connected to PB0) should illuminate on the first and third digit, but at present it lamps on every digit. What's the problem?
Thanks for your time.
It is done by bit masking. If you want to check whether or not an i'th bit of a is 1 you will do something like this:
if (a & (1 << i))
{
// Do something
}
This way all of the bits of a except the i'th one will be ANDed with zeros, thus getting a value of zero. The i'th bit will be ANDed with 1, thus not changing it's value. So the if condition will be true in case the bit is not zero, and false otherwise.
The comparison code you are presenting should work as well, but I suspect the dot variable is not containing the value you think it is containing. uint8_t dot=0101; makes it to be equal to 101 in octal base (due to the leading zero) or 65 in decimal. Not 101 in binary.

Finding next bigger number with same number of set bits

I'm working on a problem where I'm given a number n, I have to find the next larger element with same number of set bits. While searching on Internet, I found an interesting piece of code which does this in few lines of code (BIT MAGIC) here:
unsigned nexthi_same_count_ones(unsigned a) {
/* works for any word length */
unsigned c = (a & -a);
unsigned r = a+c;
return (((r ^ a) >> 2) / c) | r);
}
But I want to understand the underlying logic about the algorithm that it will work always. All the boundary cases will be handled properly.
Can someone please explain the logic in simple steps.
Thanks
In the next higher number, the leftmost 1 of the rightmost run of 1s exchanges place with the 0 to its left, while the remaining 1s move to the far right.
The code isolates lowest 1,
adds it to a (making carries ripple through to the next higher 0, inverting all those bits)
The ex-or gets the least significant run of ones, extended one position to the left.
Shifting it right two positions takes its left boundary one position right of the original one
(leaving place for that one 0 from the high position),
dividing by the lowest 1 makes room for as many 0-bits more as there were on the right end of a.
Let say we have a bit pattern such as
111100111 - representing 487 in decimal
to generate the next highest integer whilst preserving the number of 0's and 1's as in the input we need to find the first 0 bit from the right of the input that is followed by 1, and we need to toggle this bit to a 1. We then need to reduce the number of 1's on the right of this flip point by 1 to compensate for the bit we switched from a 0 to 1.
our new bit pattern will become
111101011 - 491 in decimal (we have preserved the no of bits set and not set as per the input)
int getNextNumber(int input)
{
int flipPosition=0;
int trailingZeros=0;
int trailingOnes=0;
int copy = input;
//count trailing zeros
while(copy != 0 && (copy&1) == 0 )
{
++trailingZeros;
//test next bit
copy = copy >> 1;
}
//count trailing ones
while(copy != 0 && (copy&1) == 1 )
{
++trailingOnes;
//test next bit
copy = copy >> 1;
}
//if we have no 1's we cannot form another patter with the same number of 1's
//which will increment the input, or if we have leading consecutive
//zero's followed by consecutive 1's up to the maximum bit size of a int
//we cannot increase the input whilst preserving the no of 0's and
//1's in the original bit pattern
if(trailingZeros + trailingOnes == 0 || trailingZeros + trailingOnes == 31)
return -1;
//flip first 0 followed by a 1 found from the right of the bit pattern
flipPosition = trailingZeros + trailingOnes+1;
input |= 1<<(trailingZeros+trailingOnes);
//clear fields to the right of the flip position
int mask = ~0 << (trailingZeros+trailingOnes);
input &= mask;
//insert a bit pattern to the right of the flop position that will contain
//one less 1 to compensate for the bit we switched from 0 to 1
int insert = flipPosition-1;
input |= insert;
return input;
}

Homework - C bit puzzle - Perform % using C bit operations (no looping, conditionals, function calls, etc)

I'm completely stuck on how to do this homework problem and looking for a hint or two to keep me going. I'm limited to 20 operations (= doesn't count in this 20).
I'm supposed to fill in a function that looks like this:
/* Supposed to do x%(2^n).
For example: for x = 15 and n = 2, the result would be 3.
Additionally, if positive overflow occurs, the result should be the
maximum positive number, and if negative overflow occurs, the result
should be the most negative number.
*/
int remainder_power_of_2(int x, int n){
int twoToN = 1 << n;
/* Magic...? How can I do this without looping? We are assuming it is a
32 bit machine, and we can't use constants bigger than 8 bits
(0xFF is valid for example).
However, I can make a 32 bit number by ORing together a bunch of stuff.
Valid operations are: << >> + ~ ! | & ^
*/
return theAnswer;
}
I was thinking maybe I could shift the twoToN over left... until I somehow check (without if/else) that it is bigger than x, and then shift back to the right once... then xor it with x... and repeat? But I only have 20 operations!
Hint: In decadic system to do a modulo by power of 10, you just leave the last few digits and null the other. E.g. 12345 % 100 = 00045 = 45. Well, in computer numbers are binary. So you have to null the binary digits (bits). So look at various bit manipulation operators (&, |, ^) to do so.
Since binary is base 2, remainders mod 2^N are exactly represented by the rightmost bits of a value. For example, consider the following 32 bit integer:
00000000001101001101000110010101
This has the two's compliment value of 3461525. The remainder mod 2 is exactly the last bit (1). The remainder mod 4 (2^2) is exactly the last 2 bits (01). The remainder mod 8 (2^3) is exactly the last 3 bits (101). Generally, the remainder mod 2^N is exactly the last N bits.
In short, you need to be able to take your input number, and mask it somehow to get only the last few bits.
A tip: say you're using mod 64. The value of 64 in binary is:
00000000000000000000000001000000
The modulus you're interested in is the last 6 bits. I'll provide you a sequence of operations that can transform that number into a mask (but I'm not going to tell you what they are, you can figure them out yourself :D)
00000000000000000000000001000000 // starting value
11111111111111111111111110111111 // ???
11111111111111111111111111000000 // ???
00000000000000000000000000111111 // the mask you need
Each of those steps equates to exactly one operation that can be performed on an int type. Can you figure them out? Can you see how to simplify my steps? :D
Another hint:
00000000000000000000000001000000 // 64
11111111111111111111111111000000 // -64
Since your divisor is always power of two, it's easy.
uint32_t remainder(uint32_t number, uint32_t power)
{
power = 1 << power;
return (number & (power - 1));
}
Suppose you input number as 5 and divisor as 2
`00000000000000000000000000000101` number
AND
`00000000000000000000000000000001` divisor - 1
=
`00000000000000000000000000000001` remainder (what we expected)
Suppose you input number as 7 and divisor as 4
`00000000000000000000000000000111` number
AND
`00000000000000000000000000000011` divisor - 1
=
`00000000000000000000000000000011` remainder (what we expected)
This only works as long as divisor is a power of two (Except for divisor = 1), so use it carefully.

How does this method count the number of 1s in binary representation? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
n & (n-1) what does this expression do?
Consider the following algorithm:
int count(int num)
{
int ones = 0;
while(num)
{
++ones;
num &= num - 1;
}
return ones;
}
What is the significance of num & (num-1)? How does it work?
num &= num - 1;
clears the least significant bit set in num.
This algorithm counts the bits set by clearing them and incrementing a counter until they're all gone.
To understand why it clears the least significant bit, you need to think about what decrementing does to the bits and of course understand what the & operation does.
Subtracting in binary works just as the process we were all taught in decimal as children.
You work from right (least significant) to left, simply subtracting individual digits when possible, and "borrowing" from the next digit when necessary.
When subtracting 1 from a binary number ending in a set of zeros, this "borrowing" and subtracting turns all the zeros in lower positions than the rightmost 1 to 1's and turns the rightmost 1 to a zero (because it was borrowed).
Then applying the & operator leaves all the lesser digits zero because they're zero in num, and sets the least significant bit of num to zero because it's zero in num-1.
Both of these operations leave the more significant digits unchanged.
Here's a good list of bit twiddling hacks including this one, which is due to Brian Kernighan.
Here's a more detailed (but not very well written!) answer.
There are two cases: either the least significant bit is set, then "num-1" unsets it. Or it's not set, then num-1 turns all trailing zeroes into 1, and the least significant 1 to a 0, the rest of the bits are not changed. When you "and", all unchanged bits are the same, the least significant 1 which is anded with a 0 turns into a 0 and the others remaining bits are zeroes. This is illustrated here:
num = 1000110111[1]0000
num - 1 = 1000110111[0]1111
num & (num - 1) = 1000110111[0]0000
I would point out that there is often an assembly operation to count the number of ones in a single cycle. The operation is called "popcount" and for instance in GCC, it can be accessed using "__builtin_popcount", see this link for details.
The algorithm operates like pump, moving bits effectively to right in the "num" variable. The line
num &= num - 1;
is where the work is done, there's an assignment and boolean AND operation going on at the same time. It's all about bit arithmetic.
Pom

Resources