40

While reading a tutorial I came across how to represent Float number in memory. The tutorial had an example with a floating point number.

   float a=5.2  with below Diagram

enter image description here

Can anyone please tell how this 5.2 is converted in to binary and how it is represented in memory in above the above diagram?

Community
  • 1
  • 1
Amit Singh Tomar
  • 8,380
  • 27
  • 120
  • 199

11 Answers11

52

As was said, 5.2 is represented as a sign bit, an exponent and a mantissa. How do you encode 5.2?

5 is easy:

101. 

The rest, 0.2 is 1/5, so divide 1.00000... (hex) by 5 and you get 0.3333333... (hex).

(This can be followed more easily if you consider one bit less: 0.FFFF...F / 5 = 3, so it is easy to see that 0.FFFF... / 5 = 0.33333.... That one missing bit doesn't matter when dividing by 5, so 1.0000... / 5 = 0.3333... too).

That should give you

0.0011001100110011001100110011... 

Add 5, and you get

101.00110011001100110011...         exp 0    (== 5.2 * 2^0)

Now shift it right (normalize it, i.e. make sure the top bit is just before the decimal point) and adjust the exponent accordingly:

1.010011001100110011001100110011... exp +2   (== 1.3 * 2^2 == 5.2)

Now you only have to add the bias of 127 (i.e. 129 = 0b10000001) to the exponent and store it:

0 10000001 1010 0110 0110 0110 0110 0110 

Forget the top 1 of the mantissa (which is always supposed to be 1, except for some special values, so it is not stored), and you get:

01000000 10100110 01100110 01100110

Now you only have to decide little or big endian.

This is not exactly how it works, but that is more or less what happens when a number like 5.2 is converted to binary.

Rudy Velthuis
  • 28,387
  • 5
  • 46
  • 94
  • Thanks @Rudy this is what I'am looking for. – Amit Singh Tomar Aug 02 '11 at 11:42
  • One thing i could not able to get how shift and adjust the exponent part works here – Amit Singh Tomar Aug 02 '11 at 11:47
  • 5
    The exponent counts powers of 2. The number should not change its value, so if you shift the mantissa right one bit (which is equivalent to a division by 2), the exponent must be incremented by 1 (which is equivalent to a multiplication by 2). For 5.2, you do this twice. The top bit must always be 1, and the "decimal/binary point" is right behind it. So you go from 5.2 * 2^0 to 2.6 * 2^1 to 1.3 * 2^2. The value must always be between 1 and 2 (except for special values like 0 or **very** small values, or NaNs, etc.). This is called normalization. Since the top bit is always 1, it is not stored. – Rudy Velthuis Aug 02 '11 at 11:53
  • 2
    The 'shifting' of exponents is done so you can store exponents smaller than zero. E.g. 0.125 is 1/8. That's stored as Mantissa (1)00..., sign +, Exp 124 (127-3) – MSalters Aug 02 '11 at 12:30
  • 1
    Can you please explain why did you choose `0.FFFFFFF...` to divide and also why add 127 ? – g4ur4v Feb 10 '13 at 13:47
  • 1
    0.FFFF... was chosen because it is only one least signigicant bit lower than 1 and easier to understand. 127 was chosen because that is the bias the IEEE declares for he exponent of single precision floats. The 127 is only added to store the value in the format. – Rudy Velthuis Feb 24 '13 at 19:20
  • Where can I find out how it *exactly* works according to IEEE 754 for example? – Timo Huovinen Sep 28 '13 at 21:00
  • AFAIK, IEEE does not prescribe any algorithms. Just take a look at the various `strtod()` implementations around. You can also find in ftp://ftp.ccs.neu.edu/pub/people/will/howtoread.ps how this can be done. It is not easy reading, though. – Rudy Velthuis Sep 29 '13 at 06:37
  • The zero is a special value : if the exponent and the mantissa are zeros, then the floating represented is 1 (by construction). To represent the (signed) zero, you just don't add the bia. a zero in floating representation is a signed bit and all zeros. – Senua Aug 30 '16 at 13:55
  • 1
    @Vultrao: The zeroes, the infinities, NaNs and denormals are different, indeed. The format is well defined, but not how to convert from string representation to float. – Rudy Velthuis Aug 30 '16 at 15:02
  • How 1 is replaced with .ffffffff.. and 2 is erplaced with 1.0000 for 1/2 division?? Rudy Velthuis –  Jun 02 '17 at 09:58
  • @Denise: 0.FFFF... is almost the same as 1.0000... (only the last, 52nd bit difference) but much easier to divide by 5 (F is 15, so it is easier to see why the result becomes 0.33333...) That is the only reason I used 0.FFFF... although 1.0000... is slightly more correct. The result is the same, though. That one last bit doesn't make a difference for this division. – Rudy Velthuis Jun 02 '17 at 10:23
  • okay, feeling better to understand the calculations.. Thank you @RudyVelthuis –  Jun 09 '17 at 08:53
  • Used this post [HERE](https://stackoverflow.com/a/18904441/645128). Great information. Thanks – ryyker Jan 17 '20 at 19:25
51

I think the diagram is not one hundret percent correct.

Floats are stored in memory as follows:

They are decomposed into:

  • sign s (denoting whether it's positive or negative) - 1 bit
  • mantissa m (essentially the digits of your number - 24 bits
  • exponent e - 7 bits

Then, you can write any number x as s * m * 2^e where ^ denotes exponentiation.

5.2 should be represented as follows:

0 10000001 01001100110011001100110    
S    E               M

S=0 denotes that it is a positive number, i.e. s=+1

E is to be interpreted as unsigned number, thus representing 129. Note that you must subtract 127 from E to obtain the original exponent e = E - 127 = 2

M must be interpreted the following way: It is interpreted as a number beginning with a 1 followed by a point (.) and then digits after that point. The digits after . are the ones that are actually coded in m. We introduce weights for each digit:

bits in M: 0   1    0     0      1       ... 
weight:    0.5 0.25 0.125 0.0625 0.03125 ... (take the half of the previous in each step)

Now you sum up the weights where the corresponding bits are set. After you've done this, you add 1 (due to normalization in the IEEE standard, you always add 1 for interpreting M) and obtain the original m.

Now, you compute x = s * m * 2^e and get your original number.

So, the only thing left is that in real memory, bytes might be in reverse order. That is why the number may not be stored as follows:

0 10000001 01001100110011001100110    
S    E               M

but more the other way around (simply take 8-bit blocks and mirror their order)

01100110 01100110 10100110 01000000
MMMMMMMM MMMMMMMM EMMMMMMM SEEEEEEE
Samir Talwar
  • 14,220
  • 3
  • 41
  • 65
phimuemue
  • 34,669
  • 9
  • 84
  • 115
  • 4
    Floats in IEEE-754 are represented with a 8 bit exponent and a 23 bit mantissa. That excludes the hidden bit, which is always 1 (except for denormals or NaNs or 0), so the mantissa (significand) is usually 24 bits, but only 23 are stored. The diagram shown is almost correct for little-endian floats. M should always have a top bit of 1, and the exponent is adjusted correspondingly. – Rudy Velthuis Aug 02 '11 at 11:23
  • FWIW, the diagram is correct. It is little-endian, so the topmost byte is at the topmost address. – Rudy Velthuis Dec 21 '16 at 07:20
8

The value is represented in memory in reverse order, but the confusing point may be that 5.2f is really represented as 5.1999998 due to the accuracy loss of the floating point values.

amelvin
  • 8,919
  • 4
  • 38
  • 59
beren
  • 166
  • 1
  • 8
5

Representing 5.2 is very simple in binary logic:

     8 4 2 1
5 -> 0 1 0 1

For a decimal number:

Take .2 and multiply by 2 (since it is represented in binary).

.2 X 2 = 0.4 -> take the value after the
                decimal point, don't take the value before
                the decimal point

.4 X 2 = 0.8
.8 X 2 = 1.6
.6 X 2 = 1.2
.2 X 2 = 0.4

and so on...

After this step, take the value before the decimal point from output of the above steps:

.2 X 2 = 0.4 -> take 0 from this for representing in binary form

So the final o/p of 5.2 is:

0101.00110...
MiJyn
  • 5,327
  • 4
  • 37
  • 64
vijayanand1231
  • 447
  • 1
  • 7
  • 20
3

Raw float 5.2:

01000000101001100110011001100110
^ sign bit

In memory, reverse byte order (as your diagram):

01100110011001101010011001000000
                        ^ sign bit
user703016
  • 37,307
  • 8
  • 87
  • 112
  • Thanks @Cicada but i wanted to know what is the equivalent value of 5.2 in decimal and then it can easily be understood how it is represented in memory – Amit Singh Tomar Aug 02 '11 at 09:56
2

5.2

The number is stored in form of "Sign Bit,Exponent,Mantissa. in binary form of 5 is 8 4 2 1 so 0101 and .2 is

.2*2=.4   0
.4*2=.8   0
.8*2=1.6  1

and sign bit 0 Because Number is positive.

0 0101 001....
AlexVogel
  • 10,601
  • 10
  • 61
  • 71
1

5.2 in binary 101.00110011...... ------> non normalized form 5.2 is .10100110011.... x 2^3 ------> explicit normal form 5.2 is .0100110011 x 2^3 in implicit normal form

here sign bit becomes 0 (because the number is positive) and exponent is seven bit so it is using excess 64 exponent notation so exponent will become 64+3 = 69 ie 1000101 and remaining will be mantissa (total 32bit - 7 exponent bit - 1 sign bit = 24 bit) 0100 1100 1100 1100 1100 1100

In the above example sign bit is correct Excess 64 is not applied , so not normalized but ideally it should use implicit normalization Mantissa part in second byte if you apply implicit normalization the MSB '1' will not come .

Luca
  • 1,588
  • 2
  • 22
  • 26
JOBBINE
  • 11
  • 2
0

The conversion technique posted originally on the other website is shown unnecessarily complex (although it takes us to right answer) . For memory representation of 5.2 in memory:

First convert it into simple binary system, which will give us 101.001100110011001100110011

Now change it into scientific form : 1.01001100110011001100110011 x 10^2 .

Now our sign bit is 0 as the number is positive

For exponent we need (127 + 2) upto 8 bits which gives us 10000001

Fraction is 01001100110011001100110 . (23 bits) (Discarding the leading 1 of scientific form)

=> the representation is

0 10000001 0100 1100 1100 1100 1100 110

Mojo Jojo
  • 356
  • 3
  • 14
0

Below two references really helped me understand the IEE 754 floating point number encoding in binary format,

http://www.pitt.edu/~juy9/142/slides/L3-FP_Representation.pdf

http://en.wikipedia.org/wiki/Single-precision_floating-point_format

Harish
  • 69
  • 1
  • 1
    Thanks for participating, but this question is three years old and has already been answered. Also, note that link-only answers are not well-considered on this site, because links go stale and links to large, complete documents leave the reader to work out how the document answer the questions. The best answers provide the link but offer an explanation in the particular context of the question. – Pascal Cuoq Feb 02 '14 at 05:47
0
int a;
float b=5.2;
memcpy(&a, &b, 4);
printf("%d",a);

This gives 0100 0000 1010 0110 0110 0110 1000 0001 (1084647041)

0

5.2 is represented as "01000000101001100110011001100110"

Check the Converter Applet

stacker
  • 68,052
  • 28
  • 140
  • 210