Velocity Reviews > C++ > analysis of floating point values

# analysis of floating point values

K4 Monk
Guest
Posts: n/a

 02-18-2011
hi, is there a way by which we can see a bit-by bit representation of
how a floating point value is stored? I was thinking something similar
to how we shift bits using the >> and << operators but they only work
for integers. In short, I'd like to first find out what the size of
the value is in bytes and then analyse every bit in every byte. Is
this possible?

thanks!

Jens Thoms Toerring
Guest
Posts: n/a

 02-18-2011
K4 Monk <(E-Mail Removed)> wrote:
> hi, is there a way by which we can see a bit-by bit representation of
> how a floating point value is stored? I was thinking something similar
> to how we shift bits using the >> and << operators but they only work
> for integers. In short, I'd like to first find out what the size of
> the value is in bytes and then analyse every bit in every byte. Is
> this possible?

Yes, it's possible. One way is

#include <cstdio>
#include <cstring>

int main( )
{
double d = 42.1419;
unsigned char * c = new unsigned char [ sizeof d ];
memcpy( c, &d, sizeof x );

for ( size_t i = 0; i < sizeof x; ++i )
printf( "%02x ", c[ i ] );
printf( "\n" );
delete [ ] c;
}

(I use printf() here since I'm too lazy to look up the
correct way to get properly formated hex output from
std::cout).

The 'sizeof d' bits (which could also be written as
'sizeof(double)' tells you how many bytes there are in
a double. To keep things simple a buffer of unsigned
chars of exacty this size is allocated and the bytes
of the double are directly copied over there. Then
you can print out the hexadecimal values of each of
those bytes. Splitting up a hex value into its bits is
so simple it can be done without a program (You
could also do without the extra buffer using casts
and a bit of pointer fiddling.)

Of course, those hex values won't make too much sense
without any idea what they mean. And what they mean can
differ from machine to machine. Luckily, most machines
nowadays use IEEE 754-2008 format, see e.g.

http://en.wikipedia.org/wiki/IEEE_754-2008

and the pages linked in there. Keep in mind that there
can be emdianess issues (i.e. one some machines the
low order bytes come first in memory, on others the
high order bytes and then there are further possible
variations) and that not all machines use this format.

Regards, Jens
--
\ Jens Thoms Toerring ___ http://www.velocityreviews.com/forums/(E-Mail Removed)
\__________________________ http://toerring.de

gwowen
Guest
Posts: n/a

 02-18-2011
K4 Monk wrote:
> hi, is there a way by which we can see a bit-by bit representation of
> how a floating point value is stored? I was thinking something similar
> to how we shift bits using the >> and << operators but they only work
> for integers. In short, I'd like to first find out what the size of
> the value is in bytes and then analyse every bit in every byte. Is
> this possible?

template <typename T>
for(size_t q=0;q<sizeof(T); ++q){
for (int bit=CHAR_BIT;bit > 0 ;--bit){
std::cout << ((*(chaddr+q)&(1U<<(bit-1))) ? 1 : 0);
}
}
std::cout<<std::endl;
}

int main()
{
float x = -43.43;
double y = 43.43;
print_representation(&x);
print_representation(&y);
}

K4 Monk
Guest
Posts: n/a

 02-18-2011
Thanks to all, Leigh, Jens, and gwowen...this is very useful...good
for practising C++ as well.

One quick note, I see you cast to (unsigned char*) but using sizeof
operator I see that "double" is 16 bytes (on my machine a core2duo
running linux x86_64) and unsigned char* is 8 bytes. But still the
code snippets you provided are able to print everything. Ah well, time
to go through the books again!

Paul
Guest
Posts: n/a

 02-18-2011

"Jens Thoms Toerring" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)-berlin.de...
> K4 Monk <(E-Mail Removed)> wrote:
>> hi, is there a way by which we can see a bit-by bit representation of
>> how a floating point value is stored? I was thinking something similar
>> to how we shift bits using the >> and << operators but they only work
>> for integers. In short, I'd like to first find out what the size of
>> the value is in bytes and then analyse every bit in every byte. Is
>> this possible?

>
> Yes, it's possible. One way is
>
> #include <cstdio>
> #include <cstring>
>
> int main( )
> {
> double d = 42.1419;
> unsigned char * c = new unsigned char [ sizeof d ];
> memcpy( c, &d, sizeof x );
>
> for ( size_t i = 0; i < sizeof x; ++i )
> printf( "%02x ", c[ i ] );
> printf( "\n" );
> delete [ ] c;
> }
>
> (I use printf() here since I'm too lazy to look up the
> correct way to get properly formated hex output from
> std::cout).

It's simply:
std::cout<<std::hex<< your_integer;

HTH.

Jens Thoms Toerring
Guest
Posts: n/a

 02-18-2011
K4 Monk <(E-Mail Removed)> wrote:
> Thanks to all, Leigh, Jens, and gwowen...this is very useful...good
> for practising C++ as well.

> One quick note, I see you cast to (unsigned char*) but using sizeof
> operator I see that "double" is 16 bytes (on my machine a core2duo
> running linux x86_64) and unsigned char* is 8 bytes.

In e.g.

> > unsigned char* bits = reinterpret_cast<unsigned char*>(&f);

there's a cast from 'double *' (note the '&' in front of 'f')
to 'unsigned char *', so the sizeof a double is irrelevant
here. The size of a double becomes only important when you
then iterate over the array of unsigned chars with

> > for (std::size_t i = 0; i != sizeof(f); ++i)

to stop when the end of the array (which is just the
double split up into single bytes) is reached.

Regards, Jens
--
\ Jens Thoms Toerring ___ (E-Mail Removed)
\__________________________ http://toerring.de

K4 Monk
Guest
Posts: n/a

 02-18-2011
On Feb 18, 7:26*pm, (E-Mail Removed) (Jens Thoms Toerring) wrote:
> In e.g.
>
> > > unsigned char* bits = reinterpret_cast<unsigned char*>(&f);

>
> there's a cast from 'double *' (note the '&' in front of 'f')
> to 'unsigned char *', so the sizeof a double is irrelevant
> here.

On Feb 18, 7:28 pm, Leigh Johnston <(E-Mail Removed)> wrote:
> On 18/02/2011 14:15, K4 Monk wrote:
> The cast is of a *pointer to* the double rather than of the *value of*
> the double; an unsigned char pointer is the same size as a double pointer..
>
> /Leigh

Ok I understand now. Thanks. So its basically because pointers are
always the same size regardless of whether they point to a double or a
char, and we then switch the type of the pointer so it acts as a ptr
to a char. (And the reason we do this is because double* will always
take chunks of memory in 16 bytes whereas for byte-by-byte analysis we
need a pointer which byte sized chunks, correct?) Wow I feel so much
wiser now. This is exciting, it means we can also analyze the layout
of other objects in memory...cool!

Paul
Guest
Posts: n/a

 02-18-2011

"K4 Monk" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> Thanks to all, Leigh, Jens, and gwowen...this is very useful...good
> for practising C++ as well.
>
> One quick note, I see you cast to (unsigned char*) but using sizeof
> operator I see that "double" is 16 bytes (on my machine a core2duo
> running linux x86_64) and unsigned char* is 8 bytes. But still the
> code snippets you provided are able to print everything. Ah well, time
> to go through the books again!
>

The outer loop is limited by the sizeof the float or double and not the
sizeof char.
for(size_t q=0;q<sizeof(T); ++q).

The data structure, that is the double or float, is traversed as if it were
an array of chars.
*(chaddr+q) in the inner loop, is indexing this data structure in char sized
chunks.

HTH

Jens Thoms Toerring
Guest
Posts: n/a

 02-18-2011
K4 Monk <(E-Mail Removed)> wrote:
> On Feb 18, 7:26Â*pm, (E-Mail Removed) (Jens Thoms Toerring) wrote:
> > In e.g.
> >
> > > > unsigned char* bits = reinterpret_cast<unsigned char*>(&f);

> >
> > there's a cast from 'double *' (note the '&' in front of 'f')
> > to 'unsigned char *', so the sizeof a double is irrelevant
> > here.

> On Feb 18, 7:28 pm, Leigh Johnston <(E-Mail Removed)> wrote:
> > On 18/02/2011 14:15, K4 Monk wrote:
> > The cast is of a *pointer to* the double rather than of the *value of*
> > the double; an unsigned char pointer is the same size as a double pointer.

> Ok I understand now. Thanks. So its basically because pointers are
> always the same size regardless of whether they point to a double or a
> char

Mostly correct. I'm not sure about the C++ standard, but the
C standard only guarantees that the size of a char or void
pointer is sufficient to allow a cast from other object types
to them (the back-cast is then also possible). That means that
there's a theoretical possibility that pointers to objects of
other types have smaller sizes. But I haven't seen any such
machine yet and it also rather likely doesn't make much sense
to cast from a char pointer to some other pointer (as long as
it's not a back-cast to the original type).

Be a bit careful with pointers to functions, they aren't in-
cluded in this (a function isn't an object). But even there
on most machines it also works.

, and we then switch the type of the pointer so it acts as a ptr
> to a char. (And the reason we do this is because double* will always
> take chunks of memory in 16 bytes whereas for byte-by-byte analysis we
> need a pointer which byte sized chunks, correct?)

Yes, exactly.
Regards, Jens
--
\ Jens Thoms Toerring ___ (E-Mail Removed)
\__________________________ http://toerring.de

Juha Nieminen
Guest
Posts: n/a

 02-20-2011
Leigh Johnston <(E-Mail Removed)> wrote:
> int main()
> {
> double f = 42.42;
> unsigned char* bits = reinterpret_cast<unsigned char*>(&f);
> for (std::size_t i = 0; i != sizeof(f); ++i)
> {
> unsigned char byte = bits[i];
> for (std::size_t j = CHAR_BIT; j != 0; --j)
> std::cout << (byte >> (j-1) & 1 ? '1' : '0');
> }
> }

error: 'size_t' is not a member of 'std'