On Apr 1, 4:44 am, Jack Klein <jackkl...@spamcop.net> wrote:
> On Mon, 31 Mar 2008 19:04:01 -0700 (PDT), Markus Dehmann
> <markus.dehm...@gmail.com> wrote in comp.lang.c++:
[Just a few odd comments, since the basic problem has
already been addressed...]
> > I have two integers i1 and i2, the second of which is
> > guaranteed to be between 0 and 99, and I encode them into
> > one double:
> > double encoded = (double)i1 + (double)i2 / (double)100;
The obvious question is: why? If you really do receive a value
in this format (i.e. integer part and hundredths as two separate
values), and want to treat it as a single value, fine, but then
I don't understand why you want to go the other direction later.
And I can't think of any other reason why one would want to do
this.
> This is not a very good idea, as you have found. The floating
> point data types in C, and just about every other computer
> language, use a fixed number of bits, and that limits their
> precision.
> In particular, the floating point representation in almost all
> computer systems, and certainly in all common ones programmed
> in C++, use binary fractions.
At least one architecture that is relatively common (IBM
mainframes) used base 16, and there's at least one base 8 out
there still being sold, but that doesn't change anything---all
of your comments which follow apply to any base which is a power
of 2.
So does anyone know of a machine for which there existed a C++
compiler (or even a C compiler) which doesn't use a base which
is a power of 2. I know that machines using base 10 existed in
the past, but the ones I know of were out of production long
before even C came along. Or maybe there is a compiler for IBM
mainframes which uses their decimal arithmetic, rather than
their floating point, for float and double (but I'd be very
surprised).
> That means a value like .125, or .25, or .5 is exactly
> representable in the fractional part of floating point values,
> but fractions that are not 1/(a power of 2) are not. They get
> rounded to the nearest binary fraction.
Just a nit, but that should be fractions that are not n/(a power
of 2), where n is an integer. Something like .75 is no problem
either. (Of course, if the power of 2 is greater than something
like 51, you might get problems with some of those as well.)
> > So, for example, 324 and 2 become 324.02. Now I want to
> > decode them using the function given below but it decodes
> > the example as 324 and 1, instead of 324 and 2.
> Actually, it does not become 324.02, it becomes some value
> slightly greater or smaller than 324.02, because .02 cannot be
> exactly represented in a binary fraction.
> > Can anyone tell me what's wrong and how to do this right?
> > (my code see below)
> Your basic idea is wrong.
Hard to say without really knowing what his basic idea is

.
Why does he want to do this? Anyway, two "obvious" solutions
come to mind:
-- pass through a textual representation:
std:

stringstream s1 ;
s1.precision( 2 ) ;
s1.setf( std::ios::fixed, std::ios::floatfield ) ;
s1 << encoded ;
std::istringstream s2( s1.str() ) ;
char dummyForDecimal ;
s1 >> i1 >> dummyForDecimal >> i2 ;
-- use the correct functions from C:
double i1d ;
i2 = nearbyint( 100.0 * modf( encoded, &i1d ) ) ;
i1 = i1d ;
Modf is in C90, and thus in C++ (in <cmath>). Nearbyint is an
addition of C99, and thus will be in the next version of C++,
and is possibly already available in your current C++ compiler.
If not, replace the line with
i2 = floor( 100.0 * modf( encoded, &i1d ) + 0.5 ) ;
Although less robust, it should work for positive values
constructed as above.
--
James Kanze (GABI Software) email:
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