Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C++ (http://www.velocityreviews.com/forums/f39-c.html)
-   -   analysis of floating point values (http://www.velocityreviews.com/forums/t743794-analysis-of-floating-point-values.html)

 K4 Monk 02-18-2011 12:57 PM

analysis of floating point values

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 02-18-2011 01:32 PM

Re: analysis of floating point values

K4 Monk <k4monk@gmail.com> 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 ___ jt@toerring.de
\__________________________ http://toerring.de

 gwowen 02-18-2011 01:41 PM

Re: analysis of floating point values

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 02-18-2011 02:15 PM

Re: analysis of floating point values

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 02-18-2011 02:22 PM

Re: analysis of floating point values

"Jens Thoms Toerring" <jt@toerring.de> wrote in message
news:8s7ao0Fjm8U1@mid.uni-berlin.de...
> K4 Monk <k4monk@gmail.com> 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 02-18-2011 02:26 PM

Re: analysis of floating point values

K4 Monk <k4monk@gmail.com> 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 ___ jt@toerring.de
\__________________________ http://toerring.de

 K4 Monk 02-18-2011 02:34 PM

Re: analysis of floating point values

On Feb 18, 7:26*pm, j...@toerring.de (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 <le...@i42.co.uk> 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 02-18-2011 02:46 PM

Re: analysis of floating point values

"K4 Monk" <k4monk@gmail.com> wrote in message
> 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 02-18-2011 02:56 PM

Re: analysis of floating point values

K4 Monk <k4monk@gmail.com> wrote:
> On Feb 18, 7:26Â*pm, j...@toerring.de (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 <le...@i42.co.uk> 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 ___ jt@toerring.de
\__________________________ http://toerring.de

 Juha Nieminen 02-20-2011 03:19 PM

Re: analysis of floating point values

Leigh Johnston <leigh@i42.co.uk> 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'

All times are GMT. The time now is 11:01 AM.