The number D computed by the following polynomial formula

D=(pow(i,5.)/120)-(pow(i,4.)/12)+(23*pow(i,3.)/24)-(83*i*i/12)+(571*i/30)

should always be an integer, when i=1,2,3,4,5,....
However, for some i values, each separate term may not be an integer, but when putting together (with additions and subtractions) in the above formula, any non-integer parts would be "cancelled out", and the result should be precisely an integer.

The problem is, using this formula directly, the resulting numbers are sometimes inaccurate (for some i values), with the last digit 1 off (+1 or -1) from what it should be.

So I modified the code as follows, which gets better (less errors), but still not 100% accurate (never mind the long long type--it's for when i gets large):

       long long v=pow(i,5.), w=pow(i,4.), x=23*pow(i,3.), y=83*i*i, z=571*i, vv,ww,xx,yy,zz;
       if (v%120!=0)
       {
            if (v/120.<((floor(v/120.)+ceil(v/120.))/2.))
                vv=floor(v/120.);
            else
                vv=ceil(v/120.);
       }
       else
            vv=v/120;
       if (w%12!=0)
       {
            if (w/12.<((floor(w/12.)+ceil(w/12.))/2.))
                ww=floor(w/12.);
            else
                ww=ceil(w/12.);
       }
       else
            ww=w/12;
       if (x%24!=0)
       {
            if (x/24.<((floor(x/24.)+ceil(x/24.))/2.))
                xx=floor(x/24.);
            else
                xx=ceil(x/24.);
       }
       else
            xx=x/24;
       if (y%12!=0)
       {
            if (y/12.<((floor(y/12.)+ceil(y/12.))/2.))
                yy=floor(y/12.);
            else
                yy=ceil(y/12.);
       }
       else
            yy=y/12;
       if (z%30!=0)
       {
            if (z/30.<((floor(z/30.)+ceil(z/30.))/2.))
                zz=floor(z/30.);
            else
                zz=ceil(z/30.);
       }
       else
            zz=z/30;

       long long D=v/120-w/12+x/24-y/12+z/30-16;

Hope it's clear to you the idea behind this code: it means to "cancel out" non-integer parts by truncating or rounding up the non-integer term according to whether the digit after the decimal point is less than 5 or not.

It still has errors (e.g. when i=6, D should be 29, but the output is 28; when i=12, D should be 1234, but the output is 1233; etc.).

I just realized the problem is probably when there are two terms both being exactly __.5 (the digit after the decimal point is 5), in which case both would be rounded up (ceil) to 1 by my program above, so when adding them the last digit would become 1+1=2, when it should be .5+.5=1.
When thinking more, it seem quite complicated even if to add more if...else... Any way to solve the problem?

Thanks in advance!

Edited 3 Years Ago by sgw

deleted (added in original post)

Edited 3 Years Ago by sgw

Observe that you are calculating factorials as the division : So the quickest route is to remove the common factor.
E.g

int calc(const int I)
{
  int sum(0);
  int x(I);
//   D=(pow(i,5.)/120)-(pow(i,4.)/12)+(23*pow(i,3.)/24)-(83*i*i/12)+(571*i/30)
   sum+=(120/30)*571*x;
   x*=I;
   sum-=(120/12)*83*x;
   x*=I;
   sum+=(120/24)*23*x;
   x*=I;
   sum-=(120/12)*x;
   x*=I;
   sum+=x;

   return sum/120;
   }

Note that I have used the 120 as a factor and you could put it into a constant etc. but it shows the basic trick.

Typcially I would have used an array like this:

int calc(const int I)
{
    const int topFactor[]={571,-83,23,-1,1};
    const int baseFactor[]={30,12,24,12,120}
    const int commonF(120);

    int sum(0);
    int x(1)
    for(int j=0;j<5;j++)
      {
        x*=I;
        sum+= topFactor[j]*(commonF/baseFactor[j]);
      }
    return sum/commonF;
    }

Finally the value D that you are calculating is not an interger function, and you would get rounding effects.

I am assuming that I understood the question correctly, if not please say!

Thanks for the reply! I tried your first suggestion by multiplying each term by 120 as double type, then putting them in the D forumula (adding or subtracting) as long long type, then taking D/=120 as the result. It achieved the desired result---at least for the first 100 terms (probably for the rest), it's accurate! Looking back at my tedious floor/ceil approach it was so awful ;). I'll work through your second method...

This problem really comes down to the requirement of pow having at least one non-integer parameter. Wonder why such a requirement...

Many thanks for taking your time reading and helping! :)

This article has been dead for over six months. Start a new discussion instead.