I'm kind of stumped on a project. The purpose of the project is to decode a floating point number to find it's sign, exponent, and significand, etc...

So far I've been able to get a user input float number into binary32 format using few lines of assembly code(professor told us to do it that way.)

Here is what I have so far:

#include <iostream>

using namespace std;

int main()
{
	unsigned int mask = 0x80000000;
	float fvar = 0;
	unsigned int ivar;

	// cout << "Hex value: " << hex << iValue << "\n\n";

	cout << "Enter a floating number: ";
	cin >> fvar;
	cout << "\n\n";

	_asm
	{
		MOV EAX,fvar
		MOV ivar,EAX
	}

	for (int x = 0; x < 32; x++)
	{
		if(x % 8 == 0 && x != 0)
			cout << "-";
		if(ivar & mask)
			cout << "1";
		else
			cout << "0";
		ivar = ivar << 1;
	}

	cout << "\n\n";

	return 0;
}

I am able to print the binary representation of any float number that is put in, but I'm stuck there.

How do I use bit shifting to find the "sign" of the number and display it on the screen?

or is there another way of finding the sign? Maybe by using a mask?

Recommended Answers

All 6 Replies

Firstly the 'sign' in this case is a single bit used to determine if the number is positive or negative.
For example in a exemplar five bit number.
0 0 0 0 0 = +0
0 1 0 0 0 = +1
0 0 1 0 0 = +2
0 1 1 0 0 = +3
0 0 0 1 0 = +4
The fist digit is the 'sign' bit. and setting is states that the number is negative eg:
1 0 0 0 0 = -0
1 1 0 0 0 = -1
1 0 1 0 0 = -2
1 1 1 0 0 = -3
1 0 0 1 0 = -4

for informative purposes here is how to use bitwise operators (you can ignore it).
If you can use other bitwise operators then you can use an 'and' comparison to yeild the value
with this meathod:
Number1 = 0 1 0 0 0
Number2 = 1 1 0 0 0
SignValue = 1 0 0 0 0

Number1 & SignValue is false, as the first bit is 0. (0 and 1 = 0 = false)
Number2 & SignBalue is true, as the first bit is 1. (1 and 1 = 1 = true)
Obviously some more conversion may be needed to yield an actual result

to use bit shifting is somewhat simpler and I imagine what you want to know. The difficulty is you will need to know the number of bits in your value (this *can* be dependent on environments, and is dependent on the data type used).
I will for simplicity use my five bit number from above.

every bit shift (>>) will move all the bits once in the direction and also will add a 0 to make a new bit, and discard the bit pushed out. so...
for a positive value this would yeild as follows:
>> 0 1 0 0 0 = 0 0 1 0 0
>> 0 0 1 0 0 = 0 0 0 1 0
>> 0 0 0 1 0 = 0 0 0 0 1
>> 0 0 0 0 1 = 0 0 0 0 0
So 0 is the result and we can consider this false.
for a negative value
>> 1 1 0 0 0 = 0 1 1 0 0
>> 0 1 1 0 0 = 0 0 1 1 0
>> 0 0 1 1 0 = 0 0 0 1 1
>> 0 0 0 1 1 = 0 0 0 0 1
Our resultant value is 1, thus we can consider this true.

You'll need to know some information about the number of bits in your variable, if it's stored big or little ended, etc. However this is the basic principal.

commented: excellent breakdown of bitshift... +2

Firstly the 'sign' in this case is a single bit used to determine if the number is positive or negative.
For example in a exemplar five bit number.
0 0 0 0 0 = +0
0 1 0 0 0 = +1
0 0 1 0 0 = +2
0 1 1 0 0 = +3
0 0 0 1 0 = +4
The fist digit is the 'sign' bit. and setting is states that the number is negative eg:
1 0 0 0 0 = -0
1 1 0 0 0 = -1
1 0 1 0 0 = -2
1 1 1 0 0 = -3
1 0 0 1 0 = -4

for informative purposes here is how to use bitwise operators (you can ignore it).
If you can use other bitwise operators then you can use an 'and' comparison to yeild the value
with this meathod:
Number1 = 0 1 0 0 0
Number2 = 1 1 0 0 0
SignValue = 1 0 0 0 0

Number1 & SignValue is false, as the first bit is 0. (0 and 1 = 0 = false)
Number2 & SignBalue is true, as the first bit is 1. (1 and 1 = 1 = true)
Obviously some more conversion may be needed to yield an actual result

to use bit shifting is somewhat simpler and I imagine what you want to know. The difficulty is you will need to know the number of bits in your value (this *can* be dependent on environments, and is dependent on the data type used).
I will for simplicity use my five bit number from above.

every bit shift (>>) will move all the bits once in the direction and also will add a 0 to make a new bit, and discard the bit pushed out. so...
for a positive value this would yeild as follows:
>> 0 1 0 0 0 = 0 0 1 0 0
>> 0 0 1 0 0 = 0 0 0 1 0
>> 0 0 0 1 0 = 0 0 0 0 1
>> 0 0 0 0 1 = 0 0 0 0 0
So 0 is the result and we can consider this false.
for a negative value
>> 1 1 0 0 0 = 0 1 1 0 0
>> 0 1 1 0 0 = 0 0 1 1 0
>> 0 0 1 1 0 = 0 0 0 1 1
>> 0 0 0 1 1 = 0 0 0 0 1
Our resultant value is 1, thus we can consider this true.

You'll need to know some information about the number of bits in your variable, if it's stored big or little ended, etc. However this is the basic principal.

Thank you for the explanation, it makes more sense. The thing I was confused on was, what do I exactly shift? Do I shift ivar(user input/from code), or something else? I tried to shift like this;

sign = ivar >> 31(The number is 32 bits?)

and tried to print sign on to the screen, but all I get is a 0 even if I put in a negative number.

Thank you for the explanation, it makes more sense. The thing I was confused on was, what do I exactly shift? Do I shift ivar(user input/from code), or something else? I tried to shift like this;

sign = ivar >> 31(The number is 32 bits?)

and tried to print sign on to the screen, but all I get is a 0 even if I put in a negative number.

In short your doing it the right way.
For example:

unsigned char c1=63; //0x3f, binary: 0011 1111
unsigned char result=c1>>1; // 0x1f, binary: 0001 1111

if the value stored in your 'ivar' variable *is* 32bits then shifting it 31 should work. However some discussion is required on how numbers are stored in binary and variables.

The main issue is that while a char (for example) should be eight bits (in the above example, unsigned being eight data-bits, signed being 7 and a sign bit). This is not definite, depending on the operating system, compile options, compiler and a few other things the actual number of bits in a variable can vary.

Also there are two types of binary number, Big and Little endian. This basically refers to the order of the bits themselves (if the largest value is on the left or right respectively).
In short apart from knowing that an int *can* contain a certain value (between it's minimum and maximum) you have no real knowledge of how the number is stored on the bit level. it may be stored with the sign on the left, or right, the largest value bit may be on the left, or right and it may only be 32-bits, or 64, or 128....
As you can see this puts you, as a programmer for this task in a bastard of a position. Your only option is to make a function to find the ordering, size, and position of your data and sign.

You felling intimidated yet? I am!
First read this http://www.codeguru.com/Cpp/Cpp/algorithms/math/article.php/c10243/
I'm not going to go and do all the work for you but I will lay out the theory.
Firstly we need to know the ordering of the data, big or little endian, sign left or right. To accomplish this we can do something pretty simple.

signed Type Variable = 1 //where type is your variable type, int, char, etc

This basically states we want to assign 1 to the variable so lets take a look at the theory.
with the exemplar five bit byte:
1 could be
x 0 0 0 1 (endian to the right, sign right)
0 0 0 1 x (endian to the right, sign left)
x 1 0 0 0 (endian to the left, sign right)
1 0 0 0 x (endian to the left, sign left)
I'm using an 'x' above to indicate the sign location, it would be 0.
we can find out the endian by shifting our value again by one bit in a direction and comparing it. So if we

Variable=Variable<<1

if the endian is right the number will be two:
0 0 0 1 << 1 = 0 0 1 0 = 2
if the endian is left the number will be zero:
1 0 0 0 << 1 = 0 0 0 0 = 0

So in short if Variable != 0 we are indeed dealing with a right endian, else it's left (a simple bool value could be returned from the function to indicate this)

Now we need to know where the sign is, to do this we can again use shifting. however it will vary between each case (big or little endian).
For right endian we can assign a value of -1 (-1<<0).
the result will either be:
1 0 0 0 1 (sign right, then data)
0 0 0 1 1 (data, then sign left)
If we shift this right by one we know the results we will get.
1 0 0 0 1 << 1 = 0 0 0 1 0 = +2
0 0 0 1 1 << 1 = 0 0 1 1 0 = +3
In short, if the value of a right endian number is > 2, the sign is left, else it is right.

The same can be applied to a left endian value, however we must simply shift left and apply the oppose
1 1 0 0 0 (right sign)>> 1 = 0 1 1 0 0 = +3
0 1 0 0 1 (left sign) >> 1 = 0 1 0 0 0 = +2

so in this case if the number is left signed then the value <3.

So basically:

//Left endian:
if(value << 1 == <3) LeftSign=true;
else LeftSign=false;
//right endian
if(value << 1 == >2) LeftSign=true;
else LeftSign=false;

Once you know the order of the bits you now need to know the size. you'll have to accomplish this though a loop.
if the number is left endian then we will start with the number 1, then shift left untill the value is zero (we have shifted past the total number of bits)
the code would look something like this.

signed type Variable = 1;
Int Count =0;
while ( Variable != 0)
{
     Count++;
     Variable = Variable >> 1;
}

for our four-data bits (ignoring the fith sign)
1 0 0 0 (1) (count = 0)
0 1 0 0 (2) (count = 1)
0 0 1 0 (4) (count = 2)
0 0 0 1 (8) (count = 3)
0 0 0 0 (0) (count = 4)

So we now know that we have four data bits, and obviously we add 1 for the sign bit.

with a right endian the process is identical except you shift right (<<).

So having now found the size, order, and sign location we can shift correctly.

//For left endian, left signed with 5 bits total.
SignValue = Variable << 4; //shifts sign to one bit

//For left endian, right signed with 5 bits total.
StoreValue = Variable >> 4; //shifts out everything except the sign value (places sign at highest possible number)
SignValue = Variable << 3; //shifts sign back to the one bit (not needed but acceptable practice (this way you can use SignValue== 1) 

//for right endian left signed
SignValue = Variable >> 4; // shifts sign to one bit

//for right endian right signed 
StoreValue = Variable << 4; //shifts out everything except the sign value (places sign at highest possible number)
SignValue = Variable >> 3; //shifts sign back to the one bit (not needed but acceptable practice (this way you can use SignValue== 1)

Hopefully you followed me on all that, If you *know* for certain the code is going to be used on a specific windows system with a specific compiler you can skip all of that and go research the variable type's specifics for that system/compiler. However I'd deem it good practice and a good example to throw together a full set of functions for the job (put the prototypes in a header and the functions in a cpp including it). That way you will
A. Look really awesome
B. Look really clever
C. Have a nice library for bit shifting if you need it later.
D. Have lots of members of the opposite sex want to go out with you.

D != true

In short your doing it the right way.
For example:

unsigned char c1=63; //0x3f, binary: 0011 1111
unsigned char result=c1>>1; // 0x1f, binary: 0001 1111

if the value stored in your 'ivar' variable *is* 32bits then shifting it 31 should work. However some discussion is required on how numbers are stored in binary and variables.

The main issue is that while a char (for example) should be eight bits (in the above example, unsigned being eight data-bits, signed being 7 and a sign bit). This is not definite, depending on the operating system, compile options, compiler and a few other things the actual number of bits in a variable can vary.

Also there are two types of binary number, Big and Little endian. This basically refers to the order of the bits themselves (if the largest value is on the left or right respectively).
In short apart from knowing that an int *can* contain a certain value (between it's minimum and maximum) you have no real knowledge of how the number is stored on the bit level. it may be stored with the sign on the left, or right, the largest value bit may be on the left, or right and it may only be 32-bits, or 64, or 128....
As you can see this puts you, as a programmer for this task in a bastard of a position. Your only option is to make a function to find the ordering, size, and position of your data and sign.

You felling intimidated yet? I am!
First read this http://www.codeguru.com/Cpp/Cpp/algorithms/math/article.php/c10243/
I'm not going to go and do all the work for you but I will lay out the theory.
Firstly we need to know the ordering of the data, big or little endian, sign left or right. To accomplish this we can do something pretty simple.

signed Type Variable = 1 //where type is your variable type, int, char, etc

This basically states we want to assign 1 to the variable so lets take a look at the theory.
with the exemplar five bit byte:
1 could be
x 0 0 0 1 (endian to the right, sign right)
0 0 0 1 x (endian to the right, sign left)
x 1 0 0 0 (endian to the left, sign right)
1 0 0 0 x (endian to the left, sign left)
I'm using an 'x' above to indicate the sign location, it would be 0.
we can find out the endian by shifting our value again by one bit in a direction and comparing it. So if we

Variable=Variable<<1

if the endian is right the number will be two:
0 0 0 1 << 1 = 0 0 1 0 = 2
if the endian is left the number will be zero:
1 0 0 0 << 1 = 0 0 0 0 = 0

So in short if Variable != 0 we are indeed dealing with a right endian, else it's left (a simple bool value could be returned from the function to indicate this)

Now we need to know where the sign is, to do this we can again use shifting. however it will vary between each case (big or little endian).
For right endian we can assign a value of -1 (-1<<0).
the result will either be:
1 0 0 0 1 (sign right, then data)
0 0 0 1 1 (data, then sign left)
If we shift this right by one we know the results we will get.
1 0 0 0 1 << 1 = 0 0 0 1 0 = +2
0 0 0 1 1 << 1 = 0 0 1 1 0 = +3
In short, if the value of a right endian number is > 2, the sign is left, else it is right.

The same can be applied to a left endian value, however we must simply shift left and apply the oppose
1 1 0 0 0 (right sign)>> 1 = 0 1 1 0 0 = +3
0 1 0 0 1 (left sign) >> 1 = 0 1 0 0 0 = +2

so in this case if the number is left signed then the value <3.

So basically:

//Left endian:
if(value << 1 == <3) LeftSign=true;
else LeftSign=false;
//right endian
if(value << 1 == >2) LeftSign=true;
else LeftSign=false;

Once you know the order of the bits you now need to know the size. you'll have to accomplish this though a loop.
if the number is left endian then we will start with the number 1, then shift left untill the value is zero (we have shifted past the total number of bits)
the code would look something like this.

signed type Variable = 1;
Int Count =0;
while ( Variable != 0)
{
     Count++;
     Variable = Variable >> 1;
}

for our four-data bits (ignoring the fith sign)
1 0 0 0 (1) (count = 0)
0 1 0 0 (2) (count = 1)
0 0 1 0 (4) (count = 2)
0 0 0 1 (8) (count = 3)
0 0 0 0 (0) (count = 4)

So we now know that we have four data bits, and obviously we add 1 for the sign bit.

with a right endian the process is identical except you shift right (<<).

So having now found the size, order, and sign location we can shift correctly.

//For left endian, left signed with 5 bits total.
SignValue = Variable << 4; //shifts sign to one bit

//For left endian, right signed with 5 bits total.
StoreValue = Variable >> 4; //shifts out everything except the sign value (places sign at highest possible number)
SignValue = Variable << 3; //shifts sign back to the one bit (not needed but acceptable practice (this way you can use SignValue== 1) 

//for right endian left signed
SignValue = Variable >> 4; // shifts sign to one bit

//for right endian right signed 
StoreValue = Variable << 4; //shifts out everything except the sign value (places sign at highest possible number)
SignValue = Variable >> 3; //shifts sign back to the one bit (not needed but acceptable practice (this way you can use SignValue== 1)

Hopefully you followed me on all that, If you *know* for certain the code is going to be used on a specific windows system with a specific compiler you can skip all of that and go research the variable type's specifics for that system/compiler. However I'd deem it good practice and a good example to throw together a full set of functions for the job (put the prototypes in a header and the functions in a cpp including it). That way you will
A. Look really awesome
B. Look really clever
C. Have a nice library for bit shifting if you need it later.
D. Have lots of members of the opposite sex want to go out with you.

D != true

Following what you wrote, I was able to find that the number would is right endian, and by using the count loop I was able to find that there are 32 bits.

However, following the rest of your post, when I try to shift the variable "ivar" by 31, I get a 0, even if the number I put in is negative.

If it helps, the binary form of the float number is printed with the sign at the beginning or at the left.

Following what you wrote, I was able to find that the number would is right endian, and by using the count loop I was able to find that there are 32 bits.

However, following the rest of your post, when I try to shift the variable "ivar" by 31, I get a 0, even if the number I put in is negative.

If it helps, the binary form of the float number is printed with the sign at the beginning or at the left.

So the number is right endian, left sign.
to go back to the five bit value...
X 1 0 0 0 = 1
X 0 1 0 0 = 2
X 1 1 0 0 = 3
(where X is the sign)

To clarify that means you need to do two shifts. Firstly shift to get rid of any value data
X 1 1 1 1 >> 4 = 0 0 0 0 X
Next shift back by the size -1.
0 0 0 0 X << 3 = 0 X 0 0 0
Thus yielding the sign bit as the first data bit of the variable.
So if your correct in the value being 32 bits in total with a Right Endian and a Left Sign. you need to:

TempValue = Value >> 31;
SignValue = TempValue << 30;

if(SignValue==1) 
{
          Negative = true;
}
else 
{
          Negative = false
}

Obviously if the sign is at a different end, or the endian is different you'll need to use a different method.

My final note is if this is project is worth marks you may earn more if you use the previous functions (that you used to find the order,size,etc of the value) to set some boolean values (RightEndian=true/false, RightSign=True/False) then write the function to find the sign result for each of these (if RightEndian && RightSign Func1, else if RightEndian Func2, etc) so that your program can run on any possible platform you *may* score extra marks.

If it's not worth any credits you'll be find making it simply for the platform in question.

Thank you for all of your help DarthPJB. I learned a lot from what you wrote.

As for my problem, it was something trivial I was overlooking.

#include <iostream>

using namespace std;

int main()
{
	unsigned int mask = 0x80000000;
	float fvar = 0;
	unsigned int ivar;
	unsigned int SignValue;

	cout << "Enter a floating number: ";
	cin >> fvar;
	cout << "\n";

	_asm
	{
		MOV EAX,fvar
		MOV ivar,EAX
	}

	unsigned int ivar1 = ivar;

	cout << "Hex value: " << hex << ivar << "\n\n";

	for (int x = 0; x < 32; x++)
	{
		if(x % 8 == 0 && x != 0)
			cout << "-";
		if(ivar & mask)
			cout << "1";
		else
			cout << "0";
		ivar = ivar << 1;
	}

	cout << "\n\n";

	SignValue = ivar1 >> 31;

	if(SignValue == 0)
		cout << "The Sign of the number is: " << SignValue << " Positive\n\n";
	else cout << "The Sign of the number is: " << SignValue << " Negative\n\n";

	return 0;
}

I was already shifting the variable "ivar" when printing the binary representation. So, I just made another variable, "ivar1" and made it equal "ivar" and used that to shift and it works now.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.