Re: converting float to double
- From: dcorbit@xxxxxxxxx
- Date: 20 Dec 2006 17:52:36 -0800
dcor...@xxxxxxxxx wrote:
dcorbit@xxxxxxxxx wrote:
William Hughes wrote:
Dik T. Winter wrote:
In article <1166646566.617718.113730@xxxxxxxxxxxxxxxxxxxxxxxxxxxx> "William Hughes" <wpihughes@xxxxxxxxxxx> writes:
> Dilip wrote:
...
> > THis isn't always possible. The market data vendor I connect to
> > insists that I read the stock prices as float. So when I reach into
> > the byte-stream I will have to memcpy sizeof(float) number of bytes.
> > Since everywhere else the system uses double to hold these prices, I
> > had no choice but to stuff that retreived float value into a double
> > causing all these problems.
>
> A system that uses floating point variables to store prices should
> work correctly if a price is just above or just below the
> correct price (e.g for a price of 0.010001 dollars or 0.009998
> dollars).
> The system you use does not have this property. It needs
> to be fixed.
How do you fix a system that follows the C standard?
> A possible workaround:
> Read the prices as float
> Round to the nearest cent or tenth of a cent (*)
> Convert to double
> Add a fudge factor of 0.00000001
> Now your prices will be subtly wrong, but they will be subtly wrong in
> the correct direction. This should work as well as the
> (double)(f*1000.0)/1000.0
> kludge, and will work for any value.
But after subtraction you can be subtly wrong the wrong way.
Indeed. This is not a fix. This is a kludge that might work with
a broken system.
The suggested kludge does not make the errors any worse
(we expect an error of about 10e-6 times the shareprice)
It just insures that the errors have a consistent sign. The
alternative
of not adding the fudge factor mean that there will still
be some error with unknown sign. The preferred alternatives
of avoiding or rewriting the software do not appear to be
available.
To avoid
all this is done by internally working with integers, longs, long longs,
or whatever integer size you need.
Just remember you may be dealing with the world GDP expressed
in Turkish lira. Or design your system to use floating point and be
tolerant of
small errors In the end you need to find out what the correct answer
is (this is an accounting, not a mathematical or computer question)
and design your system to give the correct answer. What internal
data type or structure you use to do this is of lesser importance.
A 64 bit integer will correctly model currency to 18 digits (with
hundredths units that gives 16 digits for the integer part).
In a mythical currency with 1,000,000 units per dollar, that would
leave 10 billion dollar transactions accurate to the penny.
With 6 digits {typically} of precision, float can barely handle a
decent paycheck. Float is one of the most onerous native C data type
that I can imagine for use with currency. Our database tools do all
calcuations in 110 digits of precision (so that things like interest
calculations for the national debt over 100 years would still yield
sensible results).
For instance,
select convert(8624231011335.27 * pow(1+(.05/4),100*4), varchar(256))
returns:
1240889574596181.05248622508978018387152633758152697346355368797339001098783576983458982091988194949844928
and {a bit more topically)
select convert(round( 8624231011335.27 * pow(1+(.05/4),100*4),2),
varchar(256))
returns:
1240889574596181.05
which is to say if the US stopped spening more than they take in, and
the national debt accrued at 5% compounding quarterly, then in 100
years the US will owe:
$1,240,889,574,596,181.05
Which is able tofit in a 64 bit integer, as pennies {barely}
;-)
A floating point version gets the 4 most significant digits correct:
C:\tmp>type f.c
#include <stdio.h>
#include <math.h>
int main(void)
{
float usnd = 8624231011335.27f *
powf(1.f+(.05f/4.f),100.f*4.f);
printf("Current debt {if stabilized} in 100 years = %20.2f\n",
usnd);
return 0;
}
C:\tmp>f
Current debt {if stabilized} in 100 years = 1240912957014016.00
C:\tmp>
Here is a double version:
C:\tmp>type d.c
#include <stdio.h>
#include <math.h>
int main(void)
{
double usnd = 8624231011335.27 * pow(1.+(.05/4.),100.*4.);
printf("Current debt {if stabilized} in 100 years = %20.2f\n",
usnd);
return 0;
}
C:\tmp>d
Current debt {if stabilized} in 100 years = 1240889574596159.20
C:\tmp>
which only misses by $21.85 (not at all surprising -- 15th digit is
dodgy)
- William Hughes
.
- References:
- Re: converting float to double
- From: Dik T. Winter
- Re: converting float to double
- From: Dilip
- Re: converting float to double
- From: William Hughes
- Re: converting float to double
- From: Dik T. Winter
- Re: converting float to double
- From: William Hughes
- Re: converting float to double
- From: dcorbit
- Re: converting float to double
- From: dcorbit
- Re: converting float to double
- Prev by Date: Re: converting float to double
- Next by Date: Re: converting float to double
- Previous by thread: Re: converting float to double
- Next by thread: Re: converting float to double
- Index(es):
Relevant Pages
|