C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

How could 0x1 become 1.4013e-45 when it is treated as float?
Goto page 1, 2, 3  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Bill David
Guest





PostPosted: Mon Nov 15, 2004 9:37 pm    Post subject: How could 0x1 become 1.4013e-45 when it is treated as float? Reply with quote



I wrote the following code and compile it with VC6 on Windows 2000:

#include <iostream>
using namespace std;

int main()
{
union {
int i;
float f;
} data;

data.i = 0x1;
cout << data.i << endl;
cout << data.f << endl;

return 0;
}

When I run it, I got the following strange output:
1
1.4013e-45

How could 0x1 become 1.4013e-45 when it is treated as float?


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Antoun Kanawati
Guest





PostPosted: Tue Nov 16, 2004 11:24 am    Post subject: Re: How could 0x1 become 1.4013e-45 when it is treated as fl Reply with quote



Bill David wrote:
Quote:
How could 0x1 become 1.4013e-45 when it is treated as float?

Because the bit pattern is being interpreted as a mantissa and an
exponent, in base-2. Then, you're trying to print it in decimal.

The bit pattern is the same, it's just a matter of interpretation.

Your microsoft docs should explain the exact details in some
obscure corner of the help pages.
--
A. Kanawati
[email]NO.antounk.SPAM (AT) comcast (DOT) net[/email]

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Jack Klein
Guest





PostPosted: Tue Nov 16, 2004 11:25 am    Post subject: Re: How could 0x1 become 1.4013e-45 when it is treated as fl Reply with quote



On 15 Nov 2004 16:37:24 -0500, "Bill David" <wxiong (AT) lucent (DOT) com> wrote
in comp.lang.c++.moderated:

Quote:
I wrote the following code and compile it with VC6 on Windows 2000:

#include using namespace std;

int main()
{
union {
int i;
float f;
} data;

data.i = 0x1;
cout << data.i << endl;
cout << data.f << endl;

return 0;
}

When I run it, I got the following strange output:
1
1.4013e-45

How could 0x1 become 1.4013e-45 when it is treated as float?

Because your code breaks one of the rules of standard C++, and causes
undefined behavior as a result. "undefined behavior" is a term with
very specific meaning in C++. It means that the C++ language standard
no longer places any requirements or guarantees on what happens,
rather like dividing by 0 in mathematics.

In your case, the undefined behavior is caused by misuse of the union.
It is only valid to read a value from a union using the same type as
was last used to store it there. The only exception to this is that
you can read any object in C++ as an array of unsigned characters.

So when you write any integer value to 'data' via 'data.i', you have
completely destroyed 'data.f'. It is no longer a representation of a
float and it no longer has a defined value.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
chris
Guest





PostPosted: Tue Nov 16, 2004 11:29 am    Post subject: Re: How could 0x1 become 1.4013e-45 when it is treated as fl Reply with quote

Bill David wrote:
Quote:
I wrote the following code and compile it with VC6 on Windows 2000:

#include using namespace std;

int main()
{
union {
int i;
float f;
} data;

data.i = 0x1;
cout << data.i << endl;
cout << data.f << endl;

return 0;
}

When I run it, I got the following strange output:
1
1.4013e-45

How could 0x1 become 1.4013e-45 when it is treated as float?


Short answer:
It could become anything it likes, or indeed crash your computer if you
do that. Writing one thing to a union and reading another is a very
naughty and undefined thing to do.

Longer answer:
Thats what you would expect. When you read the float from the union, you
aren't saying to the compiler "convert the int in here to a float",
rather you are saying "there is some combination of bits in here which
represent 1 as an int. See what they say if you try to read them as a
float". It shouldn't be surprising that the way 1 is stored as an int
and the way 1 is stored as a float are different.

If what you want is to convert an integer i to a float, you should write
(float)i.

Chris

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
M Jared Finder
Guest





PostPosted: Tue Nov 16, 2004 11:32 am    Post subject: Re: How could 0x1 become 1.4013e-45 when it is treated as fl Reply with quote

Bill David wrote:
Quote:
I wrote the following code and compile it with VC6 on Windows 2000:

#include using namespace std;

int main()
{
union {
int i;
float f;
} data;

data.i = 0x1;
cout << data.i << endl;
cout << data.f << endl;

return 0;
}

When I run it, I got the following strange output:
1
1.4013e-45

How could 0x1 become 1.4013e-45 when it is treated as float?

Floating point numbers are stored in the IEEE floating point format. I
found a good description of the format at
http://www.csit.fsu.edu/~burkardt/papers/ieee.html

In particular, it says that 0x1 is interpreted as
2^-126 * 0.00000000000000000000001_2 = 2 ^ -149 = 1.4013 * 10^-45,
which is the smallest positive value.

-- MJF

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Ron Natalie
Guest





PostPosted: Tue Nov 16, 2004 11:33 am    Post subject: Re: How could 0x1 become 1.4013e-45 when it is treated as fl Reply with quote

Bill David wrote:

Quote:
When I run it, I got the following strange output:
1
1.4013e-45

How could 0x1 become 1.4013e-45 when it is treated as float?

Because you're invoking undefined behavior. What do you think
you are try trying to do?

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Victor Bazarov
Guest





PostPosted: Tue Nov 16, 2004 11:35 am    Post subject: Re: How could 0x1 become 1.4013e-45 when it is treated as fl Reply with quote

Bill David wrote:
Quote:
I wrote the following code and compile it with VC6 on Windows 2000:

#include using namespace std;

int main()
{
union {
int i;
float f;
} data;

data.i = 0x1;
cout << data.i << endl;
cout << data.f << endl;

return 0;
}

When I run it, I got the following strange output:
1
1.4013e-45

How could 0x1 become 1.4013e-45 when it is treated as float?

This code (while not necessarily valid C++ due to use of .f member
when only .i member is set), essentially is viewed as 'internal
representation conversion'. You have shared bytes in memory:

i:
[00000000][00000000][00000000][00000001]
f:
[seeeeeee][emmmmmmm][mmmmmmmm][mmmmmmmm]

So, in the floating point value you have the exponent that is zero,
and the mantissa that has the lowest bit set. This falls into IEEE's
definition of a very small floating-point value with no hidden bit.

What did you expect?

V

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Vorticity Kappa
Guest





PostPosted: Tue Nov 16, 2004 11:36 am    Post subject: Re: How could 0x1 become 1.4013e-45 when it is treated as fl Reply with quote


"Bill David" <wxiong (AT) lucent (DOT) com> wrote

Quote:
I wrote the following code and compile it with VC6 on Windows 2000:

#include using namespace std;

int main()
{
union {
int i;
float f;
} data;

data.i = 0x1;
cout << data.i << endl;
cout << data.f << endl;

return 0;
}

When I run it, I got the following strange output:
1
1.4013e-45

How could 0x1 become 1.4013e-45 when it is treated as float?

It could do anything, anything at all. That's "undefined behavior". You're
lucky it didnt't send your email address to 80,000 viagra vendors.

00000000000000000000000000000001

has many interpretations. 1 and 1.4013e-45 are just two of them.








[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Ulrich Eckhardt
Guest





PostPosted: Tue Nov 16, 2004 11:38 am    Post subject: Re: How could 0x1 become 1.4013e-45 when it is treated as fl Reply with quote

Bill David wrote:
Quote:
#include using namespace std;

int main()
{
union {
int i;
float f;
} data;

data.i = 0x1;
cout << data.i << endl;
cout << data.f << endl;

return 0;
}

When I run it, I got the following strange output:
1
1.4013e-45

How could 0x1 become 1.4013e-45 when it is treated as float?

What did you expect?

Uli

--
FAQ: http://parashift.com/c++-faq-lite/

/* bittersweet C++ */
default: break;

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Paavo Helde
Guest





PostPosted: Tue Nov 16, 2004 11:38 am    Post subject: Re: How could 0x1 become 1.4013e-45 when it is treated as fl Reply with quote

"Bill David" <wxiong (AT) lucent (DOT) com> wrote in news:1100521231.296025.260260
@c13g2000cwb.googlegroups.com:

Quote:
I wrote the following code and compile it with VC6 on Windows 2000:

#include <iostream
using namespace std;

int main()
{
union {
int i;
float f;
} data;

data.i = 0x1;
cout << data.i << endl;
cout << data.f << endl;

return 0;
}

When I run it, I got the following strange output:

What's strange here? Reading something other from the union from what has
been put into it is undefined behavior (for any other type than unsigned
chars IIRC).

The following example demonstrates an arguably reasonable manifestation
of undefined behaviour (compile with MSVC++ on x86):

#include #include <float.h>

int main() {
// clear the FPU invalid op mask
// this is masked by default by some reason MS knows
_controlfp(_MCW_EM&~_EM_INVALID, _MCW_EM);
union {
unsigned long l;
float f;
} u;
u.l = 0xFFA00000;
std::cout << u.f + 1.0 <<"n";
}

So what do you expect in the output? Do you expect an output?

Regards
Paavo




[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Falk Tannhäuser
Guest





PostPosted: Wed Nov 17, 2004 2:08 am    Post subject: Re: How could 0x1 become 1.4013e-45 when it is treated as fl Reply with quote

Bill David wrote:
Quote:
union {
int i;
float f;
} data;

data.i = 0x1;
cout << data.i << endl;
cout << data.f << endl;
[...]
When I run it, I got the following strange output:
1
1.4013e-45

How could 0x1 become 1.4013e-45 when it is treated as float?

Frankly, what result did you expect? Reading back another data
member than the last one written to is Undefined Behaviour, with
a few exceptions (§ 9.5/1).
Well, the result you obtain looks like 2^-149 - I suppose your
implementation uses IEC 559 / IEEE 754 for 32-bit floats, meaning
that 1 bit reserved for the sign, 23 bits are for the mantissa,
and 8 bits for the exponent; the range of representable exponents
is from -125 to 128 (some possible bit patterns being reserved
for representing special values as infinity and NaN) and the
bit pattern corresponding to an 'int' equal to 1 is interpreted
as a "denormalised" float with a mantissa of 2^-24 and an
exponent of -125. For more details, you should check aforementioned
standards and the doc of your compiler or perhaps your target CPU
- and don't expect to obtain any portable behaviour when playing
with unions like that!

Falk

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Jonas Norberg
Guest





PostPosted: Wed Nov 17, 2004 2:08 am    Post subject: Re: How could 0x1 become 1.4013e-45 when it is treated as fl Reply with quote

Bill David wrote:
Quote:
How could 0x1 become 1.4013e-45 when it is treated as float?

This is the way IEEE-floats work, to learn more I suggest this link:
http://www.h-schmidt.net/FloatApplet/IEEE754.html


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
kanze@gabi-soft.fr
Guest





PostPosted: Wed Nov 17, 2004 2:09 am    Post subject: Re: How could 0x1 become 1.4013e-45 when it is treated as fl Reply with quote

"Bill David" <wxiong (AT) lucent (DOT) com> wrote


Quote:
I wrote the following code and compile it with VC6 on Windows 2000:

#include using namespace std;

int main()
{
union {
int i;
float f;
} data;

data.i = 0x1;
cout << data.i << endl;
cout << data.f << endl;

Formally, this line is illegal, and results in undefined behavior.
Pratically, for some other value of data.i (perhaps -1), it would result
in a crash.

Quote:
return 0;
}

When I run it, I got the following strange output:
1
1.4013e-45

How could 0x1 become 1.4013e-45 when it is treated as float?

You're not treating 0x1 as a float. You're treating the bit pattern
which gives 0x1 as if it were a bit pattern of a float. Most IEEE
implementations (including Intel) put the sign on the high order bit,
then the exponant, and finally the mantissa on the low order bits. The
result is that you have a float with a sign of 0 (positive), an exponent
of zero (zero or underflow), and a mantissa which is not zero (so
underflow -- note that on most non-IEEE systems I have seen, this will
either be treated as an illegal value, or as zero).

Note that while assigning data.f, then reading data.i, is also formally
undefined behavior, it will never cause a crash on most machines
(including Intel), and if data.i is output in hex or octal format, it
can even be useful for trying to "guess" the floating point format; it
can also be a useful learning experience if you're not familiar with
floating point formats.

--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Ulrich Eckhardt
Guest





PostPosted: Wed Nov 17, 2004 2:11 am    Post subject: Re: How could 0x1 become 1.4013e-45 when it is treated as fl Reply with quote

[moderators, I just accidentially sent out a partial version of this
article, please cancel that. Thank you! ]

Bill David wrote:
Quote:
#include <iostream
using namespace std;

int main()
{
union {
int i;
float f;
} data;

data.i = 0x1;
cout << data.i << endl;
cout << data.f << endl;

return 0;
}

When I run it, I got the following strange output:
1
1.4013e-45

How could 0x1 become 1.4013e-45 when it is treated as float?

What did you expect?

The point is, a float (on your system in IEEE format[1]) has a certain
binary layout that is mapped to the binary layout of the integer in the
union(Note that your mantissa has an implicit 1 at the leftmost, too).

Just wondering: what exactly were you trying to achieve? In general, except
when you are doing low-level stuff with bits and bytes, above has no use in
general C++ programming. In particular, a union is not a way to convert
between an integer and a float, its result is not even portable because the
size/alignment of float or int are not constant!

So, if you wanted to get 1.0f, a simple cast would have been enough:

// note: the cast is not strictly necessary, it would have been done
// implicitly by the compiler
float f = static_cast cout << f << endl;

Uli


[1] a quick google brought up
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore/html/_core_ieee_floating.2d.point_representation_and_microsoft_languages.asp
which is specific to your system though.
--
FAQ: http://parashift.com/c++-faq-lite/

/* bittersweet C++ */
default: break;

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Michiel Salters
Guest





PostPosted: Wed Nov 17, 2004 2:11 am    Post subject: Re: How could 0x1 become 1.4013e-45 when it is treated as fl Reply with quote

"Bill David" <wxiong (AT) lucent (DOT) com> wrote

Quote:
I wrote the following code and compile it with VC6 on Windows 2000:

You might want to use a supported C++ compiler. VC6 is officially
dead. However, your question is a general C++ one.

Quote:
#include using namespace std;

int main()
{
union {
int i;
float f;
} data;

data.i = 0x1;
cout << data.i << endl;
cout << data.f << endl;

return 0;
}

When I run it, I got the following strange output:
1
1.4013e-45

How could 0x1 become 1.4013e-45 when it is treated as float?

It isn't. What you do is illegal. You may only read one member of
a union; the last one you wrote to. In your case, that's i. If
you read f, the compiler is free to substitute any garbage it
happens to have - like the last contents of a FP register, or
the bits of i interpreted as a float.
Many compilers will do something like *(float*)&data.i, which
isn't that useful either.

In short, avoid unions. There are very few cases in C++ where they
offer a real benefit. In most cases where C programmers would use
them, C++ uses inheritance.

HTH,
Michiel Salters

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Goto page 1, 2, 3  Next
Page 1 of 3

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.