问题
I am taking in a 8 digit hexadecimal number as an IEEE 754 bit floating point number and i want to print information about that number( signbit, expbits, fractbits, normalized, denormalized, infinity, zero, NAN) floating point should be a single.
I read up on bit shifting, and i think this is how i am suppose to do it?. however, i am not 100% sure. I understand that the sign bit is found in the left most position of the number. which indicates positive or negative. How much do i shift it to find each? do i just keep shifting it to find each one? Can someone explain how i am to find each one?
would i shift by 1 to find the signbit? would i shift by 8 to get the exponent? would i shift by 23 to get the frac?
signbit should be zero
expbits should be 128
fracbits should be 0x00000000 I think...
if so how do i test it after i shift?
this is what i have so far
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
short wordOrder = 0x0100;
int HexNumber;
printf("Hex IEEE - 754\n");
if(wordOrder == 0x0100)
{
printf("\nbyte order: big-endian\n");
}
else
{
printf("byte order: little-endian\n");
}
printf("\n>");
scanf("%x", &HexNumber);
printf("\n%#x",HexNumber);
return 0;
}
my input(scanf) on how i want it..
>40000000
0x40000000
which is what its doing..
回答1:
For a single precision number the high bit is the sign, the next 8 bits are the exponent and the remaining 23 bits are the mantissa. So...
bool negative = !!(HexNumber & 0x80000000);
int exponent = (HexNumber & 0x7f800000) >> 23;
int mantissa = (HexNumber & 0x007FFFFF);
If the exponent is 255, the number is either +- infinity or NaN depending on whether the mantissa is zero (0 means infinity). If the exponent is zero then ether the number is +- zero (if the mantissa is zero) or the mantissa is the actual unnormalized fractional value.
If the exponent is anything else, there is a hidden one bit on the top of the fraction, making it 24 bits. In this case, the actual exponent can be calculated by subtracting 127 from the exponent so that it is in the range -127 to +127, the power of two exponent.
回答2:
To check whether your code is right here is a converter applet http://www.h-schmidt.net/FloatApplet/IEEE754.html
I Found the Applet was useful to check some values.
回答3:
& does a bit-by-bit and operation between two values. If one of the values is a constant & has some useful properties.
A | B | A & B
---+---+-------
0 | 0 | 0
0 | 1 | 0
---+---+-------
1 | 0 | 0
1 | 1 | 1
As you can see in the truth table, the first two rows show that if A = 0, A & B = 0. Thus, putting a zero in a mask at some position has the effect of clearing that bit.
The last two rows show that if A = 1, A & B = B. Thus, putting a one in a mask at some position has the effect of passing that bit.
So you can use constant mask to clear the bits outside a known field.
You can do the same exercise with OR (|) and XOR (^) and conclude that a mask for use with | has the effect of setting the bits of a value where the mask is 1. ^ has the effect of toggling the bits of a value where the mask is 1.
/* in response to comment*/
It's not an exponent bit it's an exponent field that is 8-bits long. So, if you build your mask as follows:
0111 1111 1000 0000 0000 0000 0000 0000 (mask === 0x7F800000)
1011 1010 0101 0110 0110 1010 1001 1010 (value)
-------------------------------------------------
0011 1010 0000 0000 0000 0000 0000 0000 (result)
You can see here that all that is left over from this operation are the bits that composed the exponent field (namely 01110100). Now if you wanted to know the value of the field, you would need to shift the result to the right by the required amount. The required amount is (in general) the zero-indexed bit position of the least significant bit of the field. For the exponent field the required shift amount is 23.
On a side note, you have to be careful when shifting to the right. We can get away with it here because we know our mask has a zero in the most significant bit, but if that were not the case we would be wise to cast our result to an unsigned value before shifting to the right. If you don't you get sign extension.
int8_t exponent = ((uint32_t) (value & 0x7F800000)) >> 23;
// the cast is not necessary in this case because the mask has a 0 in the msb
If you wanted to extract the sign bit, this cast would become important:
int8_t sign = ((uint32_t) (value & 0x80000000)) >> 31;
(I don't know where you got the notion that you would have to shift by 8 to extract the sign bit)
回答4:
In addition to the bit twiddling you're already considering, there are some library functions that allow you to dissect and scale floating point numbers.
If you have a float
or double
in hand, you can use std::frexp() to determine its significand (or mantissa) and exponent. The exponent will be integral, but the significand will be a real number either between 0.5 and 1 or zero.
回答5:
icelated asked:
Can someone explain what is going on here? Where are we coming up with the &numbers?
The & operator is the bitwise AND operator. The hex numbers are bit masks, by applying the & operator with the appropriate mask, you can isolate the bits you are interested in.
回答6:
@vicatcu, or anyone else this is
icelated..
The IEEE single precision floating point standard representation requires a 32 bit word, which may be represented as numbered from 0 to 31, left to right. The first bit is the sign bit, the next eight bits are the exponent bits, and the final 23 bits are the fraction.
Therefore to extract the sign bit we use the appropriate mask and shift by 31 to get the sign at the end? In addition to get the value of the exponent. since, its 8 bits in length - we shift 31 - 8(23) to shift it to the end? If true then the mantissa requires no shifting? Also, to extract the value we use the mask. This part confuses me. I think the mask is the hexadecimal equivelent. How do we come up with that hex number? ex: int exponent = (HexNumber & 0x7f800000) THANK YOU - i think i am getting this....
回答7:
code revised:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int HexNumber;
int a = 0x12345678;
unsigned char *c = (unsigned char*)(&a);
if (*c == 0x78)
{
printf("\nlittle-endian\n");
}
else
{
printf("\nbig-endian\n");
}
printf("\n>");
scanf("%x", &HexNumber);
printf("\n%#x",HexNumber);
bool negative = !!(HexNumber & 0x80000000);
int exponent = (HexNumber & 0x7f800000) >> 23;
int mantissa = (HexNumber & 0x007FFFFF);
printf("\nsignBit %d,", negative);
printf("expbits %d,", exponent);
printf("fractbits %#x,", mantissa);
return 0;
}
来源:https://stackoverflow.com/questions/2045018/ieee-754-find-signbit-exponent-frac-normalized-etc