Re: converting float to double
- From: "William Hughes" <wpihughes@xxxxxxxxxxx>
- Date: 27 Dec 2006 20:40:45 -0800
*** T. Winter wrote:
In article <1166861246.723939.80850@xxxxxxxxxxxxxxxxxxxxxxxxxxx> "William Hughes" <wpihughes@xxxxxxxxxxx> writes:
> *** T. Winter wrote:
...
> Consider an algorithm for compound intererest with slightly
> modified rounding, principal
> p, interest rate per period i, number of periods n, currency dollar.
>
> For period 1 to n
> p = round to nearest cent ( p + i p)
> We can calculate this using a sufficiently large integer type
> or a sufficiently large floating point type. Assume p = 100.00
> i= .05/year, the period is 6 months and there are 10 periods.
If the period is 1/2 year, the interest per period is not one half of
the year interest.
Try to do it over a five year period. A yearly
interest rate of .05 gives after five years $ 127.63 and an half-yearly
interest rate of .025 gives after five years $ 128.01. A difference
that some accountants worry about. There are specific rules how to
do interest about a period smaller than the base period (although the
rules depend on the situation).
But let me assume that the interest is 0.025 / 6 months.
> An integer implementation might look like
> long p = 10000;
> int 1000_i = 50;
> int number_of_periods n=10;
> int 1000_i_per_n;
>
> 1000_i_per_n = 1000_i / 2;
> for(i = 1;i<=n;i++){
> p += p*1000_i_per_n/1000
> if( 2*( p%1000_i_per_n) >= 1000_i_per_n ){
> p++;
> }
> }
I would do it as:
long amount = 20000; /* 2 times the amount in cents */
...
for(i = 1; i <= n; i++) {
amount += amount * 1000_i_per_n / 1000;
amount += (amount & 1);
}
amount /= 2; /* the real amount in cents after the calculations */
Your formulation is wrong. When the amount is 10769 cents (3-rd
iteration), the interest calculations give an interest of 269.225 cents,
that is rounded 269 cents. The next result is 11038 cents. Your formula
gives 11039.
Teach me to try to program at 4 am. Both attempts were
had errors. Here is a (hopefully) correct version.
#include <math.h>
int main (void){
long p = 10000;
long delta_p;
int i_1000 = 50;
int i_1000_per_n;
double dp = 100.0;
double i = .05;
double i_per_n;
int n = 200; /*number of periods*/
int j;
int i_dollars, i_cents, d_dollars, d_cents;
i_1000_per_n = i_1000 / 2;
i_per_n = i/2.0;
for(j = 1;j<=n;j++){
delta_p = p*i_1000_per_n/1000;
if( (p*i_1000_per_n%1000) >= 500 ){
delta_p++;
}
p += delta_p;
dp += dp*i_per_n;
if( fmod(dp,0.01) > 0.00495) {
dp += .01 - fmod(dp, 0.01);
} else {
dp -= fmod(dp, 0.01);
}
if( j%10 == 0 ) {
i_dollars = p/100;
i_cents = p % 100;
d_dollars = floor(dp);
d_cents = floor(100*dp+.05) - 100*d_dollars;
printf("%d %d %d %d
%d\n",j,i_dollars,i_cents,d_dollars,d_cents);
}
}
}
I see no clear advantage to using integer or floating
point. Yes, both can be optimized, but as calculation
speed is unlikely to be the bottleneck, optimization is
unlikely to be needed.
(I do not find the doubling trick to be very natural, and
it does not generalize to other forms of rounding)
- William Hughes
.
- Follow-Ups:
- Re: converting float to double
- From: *** T. Winter
- Re: converting float to double
- References:
- Re: converting float to double
- From: William Hughes
- Re: converting float to double
- From: *** T. Winter
- Re: converting float to double
- From: William Hughes
- Re: converting float to double
- From: *** T. Winter
- Re: converting float to double
- Prev by Date: Re: c / c++ : is it end of era ?
- Next by Date: Re: c / c++ : is it end of era ?
- Previous by thread: Re: converting float to double
- Next by thread: Re: converting float to double
- Index(es):