anyone care to help me here ??
Printable View
anyone care to help me here ??
Yes of course, i assume you have a decimal number as a string, like "123.4567" and you need a variable of type double to hold the result.
The function you need is atof, and is in the <stdlib.h>.
For reasons unknown to me i would prefer to use strtod.
is there any way to convert a string to an int in C? how about if I have a decimal number as a double?? how would I convert that to a floating point??
Be more specific, show some of what you need to convert.
Check this out.
okay here's an example.. say that I have a decimal number of 10 and I want to extract it to +1.0100000000000000000000e+3, something like that
You mean an assignment?
or a conversion from text?Code:int a = 10;
double d = (double)a;
Code:char s[] = "10";
double d = atof(s);
yes I mean an assignment, not from a text
+1.0100000000000000000000e+3 is 1010
so how you can "extract" 10 to this value?
to assign 10 you use
double a = 10;
to print it in the scientific notation - use %g format of printf - read about formats of printf and what formating they provide
Or,The original number posted has 22 decimal places, which is about 5 more than you can expect to get out of a "double". Some compilers and processors have larger floating point numbers "long double", implememented with for example the "80-bit Extended precision" of x86, that can give more digits - in the x86 case, you can expect about 20 digits precision with this.Code:double a = 10.0;
If you need more precise values, you need to use a special math library, such as GMP.
--
Mats
and how would I convert the decimal to binary?? is there a specific command in C that would allow me to do this?? or do I have to do this manually?
You have to do it manually, but it's not too hard. The only problem I can think of is deciding how to store the binary value. A string makes the most sense.
Code:#include <stdio.h>
// Return a value with the bit specified
// by i set and all other bits unset
#define bitmask(i) (1U << i)
int main()
{
// The number of bits in an int
const int intSize = 31;
// The decimal number to convert
int value;
int i;
printf("Please enter a decimal number to be converted: ");
scanf("%d", &value);
// Print the bits of the decimal value
for (i = intSize; i >= 0; --i)
{
// Assume bitmask(i) is unset
char bit = '0';
// Pick the character to print
if (value & bitmask(i))
{
bit = '1';
}
putchar(bit);
}
putchar('\n');
return 0;
}
Itoa can convert a number into base 2, if you will, but it's not a standard function.
I don't know of any other function to do it, though.
the code you supplied generates an error.. it's on the define part.. I know know what's wrong with that
The code compiles fine.
What compiler do you use?
I used this to compile gcc -ansi -Wall binary.c -o binary
and it says error: expected identifier or "(" before '/' token
Ah, but this is C99 or C++.
Here should be C89 compatible code:
Don't forget to include stdio.h.Code:#define bitmask(i) (1U << i)
int main(void)
{
/* The number of bits in an int */
const int intSize = 31;
/* The decimal number to convert */
int value;
int i;
char bit = '0';
printf("Please enter a decimal number to be converted: ");
scanf("%d", &value);
/* Print the bits of the decimal value */
for (i = intSize; i >= 0; --i)
{
/* Assume bitmask(i) is unset */
bit = '0';
/* Pick the character to print */
if (value & bitmask(i))
{
bit = '1';
}
putchar(bit);
}
putchar('\n');
}
Oh, I am guessing that it does not recognise the // comments. Change them to the /* */ style comments and see what happens, or maybe specify std=c99.
oh it works now.. I guess it's just the comments using // that doesn't work in my compiler, but I was able to fix it now..
I don't however understand this part:
#define bitmask(i) (1U << i)
can someone explain this to me??
and one more thing the code only works for integer numbers how about if I have a double value that I want to convert such as 1234.83?
Shift 1 left i times. Shifting is an essential part of converting between bases.
how do I shift in C?
n >> 2;
Shift n right 2 times.
n << 2;
Shift n left 2 times.
N is the variable you wish to shift and 2 is the number of times you wish to shift, so replace them as appropriate.
Well, I'd stay away from trying to convert floating points because they aren't represented as numbers, unlike integers.
You could modify the example to work with doubles, but you wouldn't get a sane output.
<< shifts bits left and >> shifts bits right.Quote:
how do I shift in C?
00000001 left shifted by 3 is 00001000. 00001000 right shifted by 3 is back to 00000001. But make sure that you only shift by a nonnegative amount and that the number you're shifting is unsigned. That way you don't have any weird problems.
yes, my assignment here is actually to create a code that will extract from a floating point number to it's mantissa and exponent
Well, that's an entirely different thing. That is not binary. And so you know, a number cannot be represented as binary. It must be a string or you would get weird results.
But I suggest you take a look at how floating points layout are, in binary terms. That's the first step.
Then you can extract them using binary operators. Specifically and.
yes I know how floating points are layed out in binary the 31st bit is the sign bit and 23-31 is the mantissa and 0-23 is the exponent.
Then go ahead and use binary operator AND to extract them.
and now lets use an example to do this, say I have a number −118.625 which is an IEEE floating point number and I want to convert that to the mantissa, sign bit, and exponent. First I know that the sign bit is 1 because it's negative and now the number.. this is where I get confused, especially doing this in C because 118.625 should be converted first into it's binary value then normalized and how would I do this??
Btw, you're describing a float, not a double.
So, do you want the actaul mantissa and exponent?
if so, you need to get the float to overlay an integer of same length, then use AND to get the portions out.
If you want something else, please clarify what you actually want.
--
Mats
yes I want the actual mantissa and exponent from a floating point number
So what have you got so far as to your code?
--
Mats
The bits are already stored in the number. Otherwise machines would not be able to understand it. To extract the specific values you would use both bitwise & (AND) and binary shifts (<<, >>).
You would have to construct a mask to isolate the parts of the number that form the mantissa and the exponent.
Wrong here, the 32nd bit is the exponent but bits are indexed 0..31 in a 32 bit number.Quote:
yes I know how floating points are layed out in binary the 31st bit is the sign bit and 23-31 is the mantissa and 0-23 is the exponent.
[31 SIGN][30-23 EXPONENT][22-0 MANTISSA]
Now for the masking part. A mask is a series of 1111 in a machine word usually positioned at the right place so that when AND'ed with a number they zero out all the bits we don't care about.
If you want the sign bit, where should the 1's be in a 32 bit unsigned integer mask and how many of them also?
If you can answer that question for the EXPONENT and the MANTISSA i might guide you to code it in C.
okay let me get this clear first, say I have a float in C which is 56.43 the 56.43 are already stored in the computer and all I need to do is to extract them by the masking techniques right??
so for a 32 bit if I want the sign bit it should be on the 31 bit?
Yes, it would. The data is always stored raw in memory, but is represented as something else depending on the type.
So all you do is extract the appropriate bits.
okay I get it, so therefore I don't have to convert the floating point to a binary first and then find the mantissa and so on. I just have to extract the right one because it's already layed out that way in the memory?
okay so I got the idea now, how do I do the AND sign at?? do I have to find the location of the memory where 56.43 is stored?? using pointers?? 56.43 is a stored in memory as a 32 bits right??
If it's a float, yes. And one way to get to the float is by pointer, another solution is to overlay it with a union of integer and float.
Also, you can avoid the AND-business altogether and use a bitfield struct - although that will make it more compiler dependant.
--
Mats
pointer seems to be a great idea say that I do this in C:
float number = 56.87
int* point = &number
then point will point to the address of the sign bit of the float?
You probably need a cast to make the compiler happy, but yes, that's the idea.
--
Mats
I just wrote this simple code:
I am trying to get the sign bit here, but somehow it gets a very large numberCode:#include <stdio.h>
int main()
{
float number = 56.73;
int* sign_pointer = (int*) &number;
int temp = *sign_pointer;
printf("%p\n", sign_pointer);
printf("%d\n", temp);
return 0;
}
Of course, you're just putting the whole data into temp.
This is what -56.43 is in binary (sign, exponent, mantissa):
1 10000100 11000011011100001010010
So number containers
1 10000100 11000011011100001010010
Then the value of number is assigned to temp, so temp becomes
1 10000100 11000011011100001010010
You need to use binary and to extract the bits you want. Then you need to shift the bits into the correct position to get a valid result.
Btw, consider using a negative number. So when you get 1, you know that you got the right bit, since the sign bit is set when the number is negative.
could you give me an example of using this and binary to extract the bits in C code, because I don't quite get it. an example might really help.. thanks
Binary AND works with a mask.
It's simple, really...
Quote from MSDN.Quote:
The bitwise AND operator (&) compares each bit of the first operand to the corresponding bit of the second operand. If both bits are 1, the corresponding result bit is set to 1. Otherwise, the corresponding result bit is set to 0.
So say you have this
This sample will extract the 5th bit. But if you want to use it, you want it in the correct position, because the number will be 0x8, not 0 or 1.Code:char c = 0xFF;
char mask = 0x8;
char c2 = c & mask;
This code shifts the number right 4 times, back into its rightful position as bit 0. Thus it will be 0 or 1.Code:c2 >>= 4;
Why use a pointer? The general rule for working with bits is that unsigned types are the best to use even though it really doesn't matter, it is much better when viewed hexadecimally.
Try this see what it outputs. Binary and hexademical arithmetic are not taught in school usually but they are not that tough to understand... Numbers are absolute quantities that can be represented in various ways.Code:float number = 56.73f;
unsigned int sign_mask = 0x80000000; /* Bit 31 */
/* Alternative option */
unsigned int sign_mask = (1U << 31); /* The same as above */
unsigned int sign_bit;
sign_bit = number & sign_mask;
/* sign_mask is : 1000 0000 0000 0000 0000 0000 0000 0000
in binary therefore, sign_bit is either all zeros or like sign mask in binary,
which is a large number of course. */
printf("%#08x\n", sign_mask);
printf("%#08x\n", sign_bit);
To get the sign bit (untested, so I may have done something stupid, apart from not actually writing main and all the rest):
Code:#define SIGN_BIT (1 << 31)
float first = -56.43;
int *second;
unsigned int sign;
second = (int *) &first;
sign = (*second) & SIGN_BIT; /* note one ampersand for bitwise-and */
True enough.
You can't use binary & with floats. Your original solution works. Use an integer type:
float d = -56.43f;
uint32_t nTemp = *(uint32_t*)&d;
okay I tried another code:
however it does not print a 1 or 0 instead of a very large numberCode:#include <stdio.h>
#define SIGN_BIT (1U << 31)
int main()
{
float first = -56.43;
int *second;
unsigned int sign;
second = (int *) &first;
sign = (*second) & SIGN_BIT; /* note one ampersand for bitwise-and */
printf("%u\n", sign);
return 0;
}
Because there is a difference between what you have:
10000000000000000000000000000000
And how 1 or 0 is represented:
00000000000000000000000000000001
OR
10000000000000000000000000000000
Shift the bit into correct position.
so it should be 1U >> 31 then??
No, read again. After you use binary AND, your sign has the value of
10000000000000000000000000000000
So you need to shift that left-most bit so it becomes
00000000000000000000000000000001
THEN you have your answer.
So shift the variable sign.
The define SIGN_BIT is the mask. You use it to extract the bit you want, so you shouldn't modify that.
oh yeah I forgot about that, now I am going to try to create the code for the mantissa and exponent and post here if I have problems
I'll admit that I started fiddling with it, too. Though I've already solved it, I'll just show how I extracted the sign bit since you figured that one out already (it's fun! :D):
Good luck!Code:float d = -56.43f;
uint32_t nTemp = *(uint32_t*)&d;
uint8_t Sign = (nTemp & 0x80000000) >> (23 + 8);
oh one more question, is there any way in C so that when I extract the mantissa I can have the hidden bit in the value??
What do you mean "hidden bit"?
the 1. x x x x x x
where 1 is the hidden bit
Still not sure what you're on about, but it's just bits. You can set any of them. Or you zero them out, both as you like. You can hide some bits in there if you want, of course, but they'll also be part of the number.
Do you mean the sign bit? If you've already extracted it, then you know whether the number is supposed to be positive or negative. You can then multiply appropriately.
Edit: or do you mean the implicit 1 in front of the mantissa? It's not stored with the number (hence implicit), so you can't extract it. The way to check if it's supposed to be there is to extract the exponent: if the exponent is 0, the number is denormalized so there's no implicit 1.xxx, otherwise there is.
is there anyway to append bits in C?? because the exponent is located between bits 23-30 and I need to get that bits and transformed it into hexadecimal.. how would I do this?
and how would I move one bit to the other?? if I add one it will add an integer 1 not a bit
You can convert it or print it as hex.
printf("%x", mantissa)
For example.
You move bits using shift >> and <<. As in my code I posted.
You can set bits using binary OR.
You can zero bits using a combination of binary AND and XOR:
Code:char c = 0xFF;
c & ~(0x8); // Zero fifth bit
here's the code to find the exponent, is this right??
Code:#include <stdio.h>
#define SIGN_BIT (1U << 31)
#define EXPONENT (11111111U << 31)
int main()
{
float first = 56.43;
int *second;
unsigned int sign;
unsigned int mantissa;
second = (int *) &first;
sign = (*second) & SIGN_BIT; /* note one ampersand for bitwise-and */
sign = sign >> 31;
mantissa = ((*second) << 1) & EXPONENT;
mantissa = mantissa >> 23;
printf("%u\n", sign);
printf("%u\n", mantissa);
return 0;
}
Exponent is correct. Mantissa is way off.
I'll help you, though. The easiest way to construct a proper mask to use is first to write down, in binary, the entire mask. I'll take the sign bit as example:
10000000000000000000000000000000 (31th bit signed, rest 0).
Use Windows Calculator (you are using Windows, I hope?), select scientific mode, select binary, past your mask there.
Select hex and copy your new mask.
Doing that gives me 80000000.
So I do nTemp & 0x80000000 and I get the sign bit. The same hold true for the other parts as well.
Then shift into position.
oh I am sorry, I meant exponent here
11111111U is not eight consecutive bits. If you want eight consecutive bits, the easiest way (I think) is to use hex notation: 0xff. Also note that you don't want to shift 31 places, because the exponent is not 31 places away from where you start.
And exponent is also way off, as tabstop notes. I find it easiest to just construct the mask directly instead of shifting, but it's up to you. You could also just construct a mask from 1111 1111 and shift it into place.
so is this right now:
Code:#include <stdio.h>
int main()
{
float first = -10.000000;
int *second;
unsigned int sign;
unsigned int exponent;
unsigned int mantissa;
second = (int *) &first;
sign = (*second) & 0x80000000; /* note one ampersand for bitwise-and */
sign = sign >> 31;
exponent = ((*second) << 1) & 0xff000000;
exponent = exponent >> 23;
mantissa = ((*second) << 9) & 0xfffffe00;
mantissa = mantissa >> 9;
printf("%u\n", sign);
printf("%u\n", exponent);
printf("%x\n", mantissa);
return 0;
}
You don't ever ever ever ever ever ever ever ever ever ever want to shift *second.
As to your bit masks, do you know how to convert binary to hex? Let me take a completely arbitrary example: let's suppose I want to use the bitmask 11000110001100011000110001100011. I would break it up into groups of four:
1100 0110 0011 0001 1000 1100 0110 0011. I can then turn each group of four into a single hex digit: 12 6 3 1 8 12 6 3 -> 0xc6318c63. So write down your bitmask for exponent and mantissa and convert it to hex.
oh so we don't want to shift second?
Exponent is right. You did that excellent.
Mantissa is correct, by chance I believe.
Exponent is not correct.
You don't need to shift the actual number. Shift the mask or construct the correct mask in the first place.
It's far easier to just use a calculator to do the job. And there's nothing wrong with it, either.
Windows provides an excellent tool for this. I'm sure other OSes do too.
I'd avoid it, if I were you. You're essentially destroying original data by doing that.
In this case, you can get away with it, but next time you might not be so lucky.
I've revised the code so that I won't have to change second, let me know if I messed up.
and how do I directly eliminate the excess -127 in the exponent??Code:#include <stdio.h>
int main()
{
float first = -10;
int *second;
unsigned int sign;
unsigned int exponent;
unsigned int mantissa;
second = (int *) &first;
sign = (*second) & 0x80000000; /* note one ampersand for bitwise-and */
sign = sign >> 31;
exponent = (*second) & 0x7F800000;
exponent = exponent << 1
exponent = exponent >> 23;
mantissa = (*second) & 0x7FFFFF;
mantissa = mantissa << 9;
mantissa = mantissa >> 9;
printf("%u\n", sign);
printf("%u\n", exponent);
printf("%x\n", mantissa);
return 0;
}
Well done. You have the right mask, but you need to stop needlessly shifting around the numbers.
Shift them right so that the first bit in the number becomes the 0th bit in the whole number.
Shift it into the right place and you don't have to worry about "excess" data. It will be as it should be.
In particular the above seems very pointless...Code:mantissa = mantissa << 9;
mantissa = mantissa >> 9;
--
Mats
This is also wrong. Why would you shift the exponent left when you want it at the beginning, to the right? If you remove the left shift, it's correct.Code:exponent = exponent << 1
exponent = exponent >> 23;
okay I fixed all the errors I have, now how do I translated the mantissa into hexadecimals. like for instance if it's -10 then it should be 0xa00000 in the mantissa
Your bits are in the wrong position, that's why it seems you are getting "excess."
You can use my function for debugging:
It will print all bits of a number. Make sure there are no "0" to the right-most, because if there it, you didn't shift it right.Code:void PrintBits(uint32_t nNumber)
{
char Binary[sizeof(nNumber) * 8 + 1] = {0};
char Binary2[sizeof(nNumber) * 8 + 1] = {0};
for (int i = sizeof(nNumber) * 8 - 1; i >= 0; i--)
{
if (nNumber & (0x1 << i))
Binary[i] = '1';
else
Binary[i] = '0';
}
for (int i = sizeof(nNumber) * 8 - 1, j = 0; i >= 0; i--, j++) Binary2[j] = Binary[i];
for (int i = 0; i < sizeof(nNumber) * 8; i++)
{
if (i == 1) cout << " ";
else if (i == 1 + 8) cout << " ";
cout << Binary2[i];
}
cout << "\n";
}
Shift it all the way to the right. And be careful not to shift too much.