Ayala 发表于 2016-8-3 15:42:58

大加减乘除 c源码 (测试)

本帖最后由 Ayala 于 2016-12-3 18:58 编辑

编译 命令行
详见帖 https://www.0xaa55.com/forum.php?mod=viewthread&tid=1885&page=1#pid6571
有bug请反馈 不擅长c代码 写的太难看

/*
#include <Windows.h>
#include <WinBase.h>
#include <malloc.h>
*/



#ifndef Uint8B
typedef unsigned __int64 Uint8B;
#endif

#pragma pack(8)

/*
#if !defined(_LARGE_INTEGER) && !defined(LARGE_INTEGER)
typedef union _LARGE_INTEGER
{
struct
{
    __int32 LowPart;
    __int32 HighPart;
}u;
__int64 QuadPart;
}LARGE_INTEGER;
#endif

typedef struct
{
struct            //
{
    __int32 n;
    __int32 max;
}len;
__int64*databuffer;      //
void*   filehandle;//
__int64   mod;
}polynomial;

typedef polynomial* ppolynomial;
*/

typedef struct
{
        double real;
        double img;
}complex;
typedef complex* pcomplex;
#pragma pack()

#ifdef cp
#undef cp
typedef complex cp;
#else
typedef complex cp;
#endif

#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif


#ifdef x86_xp
#ifndef _ftol2

__int64 _ftol2(double x)
{
__int16 e,ee;
__int64 r;
__asm
{
    fld qword ptr x
   
    fstsw word ptr
    mov ax,word ptr
    or ah,0xc
    mov word ptr ,ax
   
    fldcw word ptr
    fistp qword ptr
    fldcw word ptr
   
    mov eax,dword ptr
    mov edx,dword ptr
}
}
#endif
#endif



double sin(double x);
double cos(double x);

double acos(double x);
double fmod(double x,double y);
double fabs(double x);
double floor(double x);
double ceil(double x);

void print(__int64 x[],int nx);
void convertd(__int64 a[],int na,__int64 b[],int *nb);
void trim(__int64 x[],int *nx);



__int64 polynomial_cmp(__int64 a[],int na,__int64 b[],int nb);

void polynomial_add(__int64 a[],int na,__int64 b[],int nb,__int64 c[],int *nc);
void polynomial_sub(__int64 a[],int na,__int64 b[],int nb,__int64 c[],int *nc);
void polynomial_mul(__int64 a[],int na,__int64 b[],int nb,__int64 c[],int *nc);
void polynomial_div(__int64 a[],int na,__int64 b[],int nb,__int64 c[],int *nc,__int64 d[],int *nd);



#define N 1<<16


__int64 a;
__int64 b;
__int64 c;
__int64 d;
__int64 t;

double PI;


#define _MOD 100
#define fmt "%02I64d"
#define LEN2

void   add(complex   a,complex   b,complex   *c)      
{
//_fpreset();
        c->real        =a.real        +        b.real;      
        c->img        =a.img        +        b.img;      
}

void   sub(complex   a,complex   b,complex   *c)      
{
//_fpreset();
        c->real=a.real-b.real;      
        c->img=a.img-b.img;      
}

void   mul(complex   a,complex   b,complex   *c)      
{      
//_fpreset();
        c->real        =a.real*b.real-   a.img*b.img;      
        c->img        =a.real*b.img   +   a.img*b.real;      
}      


void   divi(complex   a,complex   b,complex   *c)      
{      
//_fpreset();
        c->real        =(a.real*b.real+a.img*b.img)/(b.real*b.real+b.img*b.img);      
        c->img        =(a.img*b.real-a.real*b.img)/(b.real*b.real+b.img*b.img);
}       

   
void bit_reverse_copy(cp a[], int n, cp b[])   
{   
    int i, j, k, u, m;   
    for (u = 1, m = 0; u < n; u <<= 1, ++m);   
    for (i = 0; i < n; ++i)   
    {   
      j = i; k = 0;   
      for (u = 0; u < m; ++u, j >>= 1)   
            k = (k << 1) | (j & 1);   
      b = a;   
      ////printf("b[%d]=%.2lf+%.2lfi\n",k,b.real,b.img);
    }   
}



void FFT(cp _x[], int n, int flag)   
{   
    static cp x={0.0};   
    int i, j, k, kk, p, m;   
    double alpha;   
   
    cp wn,w,u,t,up,down;
    //_fpreset();
   
    bit_reverse_copy(_x, n, x);
   
    alpha = 2.0 * acos(-1.0);
    if (flag) alpha = -alpha;   
   
    for (i = 1, m = 0; i < n; i <<= 1, ++m);   
   
    for (i = 0, k = 2; i < m; ++i, k <<= 1)   
    {   
      wn.real = cos(alpha / k);
      wn.img= sin(alpha / k);
      for (j = 0; j < n; j += k)   
      {   
            w.real = 1.0;
            w.img= 0.0;
            kk = k >> 1;   
            for (p = 0; p < kk; ++p)   
            {      
                mul(w, x,&t);
                add(x,t,&up);
                sub(x,t,&down);
               
                x      = up;   
                x = down;   
               
                mul(w,wn,&u);
                w = u;   
            }   
      }   
    }   
    memcpy(_x, x, sizeof(cp) * n);   
}   


__int64 IsTrue(__int64 a[],int na)
{ int i;__int64 t=0;
if (na)
{
    for (i=0;i<na;i++) t |= a;
}
return t;
}



__int64 polynomial_cmp(__int64 a[],int na,__int64 b[],int nb)
{
static __int64 pe;int te;__int64 t;
polynomial_sub(a,na,b,nb,pe,&te);
if (0==te) t|=-1;
else t=(__int64)IsTrue(pe,te);
return t;
}

void polynomial_add(__int64 a[], int na, __int64 b[], int nb, __int64 c[], int *nc)
{
int i,j,k;__int64* pD;

if (na>nb)
{
    k=nb;
    j=na;
    pD=a;
}
else
{
    k=na;
    j=nb;
    pD=b;
}


*nc=j;

for (i=0;i<k;i++) c=a+b;

for (i=k;i<j;i++) c=pD;

//convertd(c,*nc,c,nc)
}



void polynomial_sub(__int64 a[], int na, __int64 b[], int nb, __int64 c[], int *nc)
{
int i,j=na,k=nb;

if (j<k)
{
    *nc=0;
}
else
{
   
    for (i=0;i<k;i++) c =a-b;
    for (   ;i<j;i++) c =a;
   
    for (i=0;i<j-1;i++)
    {
      //printf("c[%d]=%I64d\n",i,c);
      if (c<0)
      {
      c+=_MOD;
      c-=1;
      }
    }
   
    trim(c,&j);
    ////printf("i=%d\n",i);
    if (c<0) *nc=0;
    else *nc=max(j,1);
    ////printf("i=%d\n",i);
}
}


void polynomial_mul(__int64 a[], int na, __int64 b[], int nb, __int64 c[], int *nc)   
{   
    static cp x, y,u;
    int i, n;
    //_fpreset();
   
   
    i = max(na, nb) << 1;   
    for (n = 1; n < i; n <<= 1);
   
    for (i = 0; i < na; ++i)
    {
      x.real = a;
      x.img= 0;
      ////printf("x[%i]=%.2lf+%.2lfi\n",i,x.real,x.img);
    }
   
    for (; i < n; ++i)
    {
      x.real = 0;   
      x.img= 0;
    }
   
    FFT(x, n, 0);   
   
   
    for (i = 0; i < nb; ++i)
    {
      y.real = b;   
      y.img= 0;
      ////printf("y[%i]=%.2lf+%.2lfi\n",i,y.real,y.img);
    }
   
    for (; i < n; ++i)
    {
      y.real = 0;   
      y.img= 0;
    }
   
    FFT(y, n, 0);   
   
    for (i = 0; i < n; ++i)
    {
      ////printf("x[%i]=%.2lf+%.2lfi\n",i,x.real,x.img);
      ////printf("y[%i]=%.2lf+%.2lfi\n",i,y.real,y.img);
      mul(x,y,&u);   
      ////printf("u[%i]=%.2lf+%.2lfi\n",i,u.real,u.img);
    }
   
    FFT(u, n, 1);   
   
    for (i = 0; i < n; ++i)   
    {   
      ////printf("c[%d] .lf = %.53lf\n",i,u.real / n + 0.5);
#ifdef x86_xp
      c = _ftol2(u.real / n + 0.5);
#else
      c = (__int64)(u.real / n + 0.5);
#endif         ////printf("c[%d]I64d = %I64d\n",i,c);
    }   
    for (i = na + nb - 1; i > 1 && !c; --i);
    *nc = i;
}   


void polynomial_div(__int64 a[], int na, __int64 b[], int nb, __int64 c[], int *nc,__int64 d[],int *nd)   
{   
static __int64 pa,pb,pc;
int i,j,k,t;
int ta,tca,tb,tc,te,rc;
__int64 t0,t1,t2,tt;
__int64 *pca;
signed __int64 flag;

if (na<nb)
{
    c=0;
    *nc =1;
    for (i=0;i<na;i++) d=a;
    *nd = na;
}
else
{
      for (i=0,ta=na;i<na;i++) pa=a;
      
      for (i=0,tb=nb;i<nb;i++) pb=b;
      
      for (i=0,*nc=0;i<na;i++) c&=0;
      
      for (k=ta-tb,j=k,*nc=k+1;j>=0;j--)
      {
          pca=&pa;
          tca=tb;
         
         
          flag = polynomial_cmp(pca,tca,pb,tb);

         
          if (flag>0)//pca>pb
          {
            t0=pca;
            tt=pb;
            t1=t0 / (tt+1);
            t2=t0 / tt;
            convertd(pca,tca,pca,&tca);
            
            //printf("line:%d t1=%I64d,t2=%I64d,tt=%I64d\nt0=%I64d\t\n",__LINE__,t1,t2,tt,t0);
            
            tt=(t1+t2+1)/2;
            
            while (t1!=t2)
            {
            tt=(t1+t2+1)/2;
            pc=tt;tc=1;
            
            //printf("line:%d t1=%I64d,t2=%I64d,tt=%I64d\n",__LINE__,t1,t2,tt);
            //printf("line:%d,tb=%d,pb=\t",__LINE__,tb);
            //print(pb,tb);
            
            
            polynomial_mul(pc,tc,pb,tb,pc,&tc);
            convertd(pc,tc,pc,&tc);
            //printf("line:%d,tca=%d,pca=\t",__LINE__,tca);
            //print(pca,tca);
            //printf("line:%d,tc=%d,pc=\t",__LINE__,tc);
            //print(pc,tc);
            
            flag = polynomial_cmp(pca,tca,pc,tc);
            
            if (flag==0)
            {
                break;
            }
            else if (flag>0)
            {
                t1=tt;
            }
            else
            {
                if (tt-t1<=1)
                {
                  tt=t1;
                  break;
                }
                t2=tt;
            }
      
            }
            /*
            printf("line:%d,tt=%I64d\n",__LINE__,tt);
            */
            c=tt;
            
            
            pc=tt;
            tc=1;
            
            polynomial_mul(pc,tc,pb,tb,pc,&tc);
            convertd(pc,tc,pc,&tc);
            /*
            printf("line:%d,tca=%d,pca=\t",__LINE__,tca);
            print(pca,tca);
            printf("line:%d,tc=%d,pc=\t",__LINE__,tc);
            print(pc,tc);
            */
            polynomial_sub(pca,tca,pc,tc,pca,&tca);
            convertd(pa,ta,pa,&ta);
            trim(pa,&ta);
            /*
            printf("line:%d,tca=%d,pca=\t",__LINE__,tca);
            print(pca,tca);

            printf("line:%d,ta=%d,pa=\t",__LINE__,ta);
            print(pa,ta);
            */
            
          }
          else if (flag==0)
          {
            c=1;
            /* */
            polynomial_sub(pca,tca,pb,tb,pca,&tca);
            convertd(pa,ta,pa,&ta);
            trim(pa,&ta);
            
          }
          else c=0;
         
          if ((tca==tb)&&(ta>tb))
          {
            pa+=_MOD*pa;
            pa&=0;
            ta-=1;
            j=max(j,1);
          }
          else if (tca>tb)
          {
            printf("line:%d Error\n",__LINE__);
            system("pause");
          }
          //printf("*****************************************************\n");
      }
      
      convertd(pa,ta,pa,&ta);
      for (i=0;i<ta;i++) d=pa;
      *nd = max(i,1);
      
      
      convertd(c,*nc,c,nc);
      trim(c,nc);
      //print(c,*nc);
      
      //free(pheap);
      
   
}

}   


void convert(char *s, __int64 a[], int * n)   
{   
    int len = strlen(s), i, j, k,r;
    for (r = 0, i = len - LEN; i >= 0; i -= LEN)   
    {   
      for (j = k = 0; j < LEN; ++j)
      {
            k = k * 10 + (s - '0');   
      }
      a = k;   
      ////printf("@207 k = %d\n",k);
    }   
    i += LEN;   
    if (i)   
    {   
      for (j = k = 0; j < i; ++j)
      {
            k = k * 10 + (s - '0');   
      }
      a = k;   
      ////printf("@217 k = %d\n",k);
    }   
    *n=r;
    ////printf("@220 r = %d\n",r);
}   

void trim(__int64 s[],int *ns)
{
int i,j;
j=*ns;
if (j>1)
{
    while (j>1&&s==0) j--;
    *ns=j;
}
}
void convertd(__int64 s[],int ns, __int64 a[], int * n)   
{   
    int i,ii;__int64 t1,t2;
   

    if (ns)
    {
      for (i=0,t1=0; i < ns; ++i)   
      {   
      t2 = t1 + s;   
      a = t2 % _MOD;   
      t1 = t2 / _MOD;   
      }   
      for (; t1; t1 /= _MOD) a = t1 % _MOD;   

      *n=i;
    }
    ////printf("@262 r = %d\n",r);
}

void print(__int64 a[], int n)   
{   
    if (n)
    {
      printf("%I64d", a[--n]);   
      while (n>0) printf(fmt, a[--n]);   
    }
    else printf("Error\n");
    puts("");   
}   


char buf;   

#ifndef EOF
#define EOF (-1)
#endif

#ifndef false
#define false 0
#endif

#ifndef true
#define true 1
#endif



__int64 ddd (__int64 a[],int* na)
{
int i,k;__int64 t=0;

////printf("na=%d\n",*na);
if ((1>=a) && (1>=*na)) goto done;

for (i=0;i<*na,0==a;++i);

////printf("a[%d]=%I64d\n",i,a);
a--;
////printf("a[%d]=%I64d\n",i,a);
if (k=*na,0==a[--k]) *na-=1;

////printf("i=%d,na=%d\n",i,*na);

for (k=0;k<i;k++) a+=_MOD-1;

for (i=0;i<=*na;t |= a);

*na=max(*na,1);

//system("pause");
done:
return t;
}



int mainCRTStartup()   
{   
    int i,na, nb, nc, nd, nt,sign,e;   
    __int64 t1, t2,M;double f1,f2;
    long Ticks;

    //conc();
    printf("******************************************************\n");
    printf("*                                                    *\n");
    printf("******************************************************\n");
    nc&=0;
    while (scanf("%s", buf) != EOF)   
    {   
      if (buf== 'c')
      {
      system("cls");
      continue;
      }
      else if (buf== 'q')
      {
      break;
      }
      else if ((nc<N) && ( \
                (buf== '+') || \
                (buf== '-') || \
                (buf== '*') || \
                (buf== '/') || \
                (buf== '!')    \
               ))
      {
      for (i=0;i<nc;i++) a=c;
      na=nc;
      }
      else
      {
      convert(buf, a, &na);
      scanf("%s", buf);
      }
      
      if      (buf== '+')
      {
      
          scanf("%s", buf);
          convert(buf, b, &nb);   
          polynomial_add(a, na, b, nb, c, &nc);
          convertd(c,nc,c,&nc);
          print(c, nc);
      }
      else if (buf== '-')
      {
          scanf("%s", buf);
          convert(buf, b, &nb);   
          polynomial_sub(a, na, b, nb, c, &nc);
          convertd(c,nc,c,&nc);
          print(c, nc);
      }
      else if (buf== '*')
      {
          scanf("%s", buf);
          convert(buf, b, &nb);   
         
          polynomial_mul(a, na, b, nb, c, &nc);
          convertd(c,nc,c,&nc);
          print(c, nc);
      }
      else if (buf== '/')
      {
          scanf("%s", buf);
          convert(buf, b, &nb);
         
          polynomial_div(a, na, b, nb, c, &nc,d,&nd);
         
         
          convertd(c,nc,c,&nc);
          convertd(d,nd,d,&nd);
          print(c, nc);
          print(d, nd);
      }
      else if (buf== '!')
      {
          if (na<=8)
          {
            t=a;
            t=a;
            nt=na;
            
            while (ddd(t,&nt))
            {
            polynomial_mul(a, na, t, nt, c, &nc);
            convertd(c,nc,a,&na);
            }
            
            convertd(c,nc,c,&nc);
            print(c, nc);
          }      
      }
      else if (buf== 'c')
      {
      system("cls");
      }
      else if (buf== 'q')
      {
      break;
      }
      else
      {
          printf("+-*/!\n");
      }   
      printf("******************************************************\n");
    }

    return 0;   
}

0xAA55 发表于 2016-8-5 17:43:10

建议将add mul divi等函数重命名为complex_add complex_mul complex_div,然后将这些不导出的函数用static修饰。

human_rights 发表于 2018-1-14 10:18:48

支持楼主。不擅长c代码都能写这么好!最主要是代码贴出来了很方便参考。
就是有些函数部分地方我看不懂,能加些注释就好了:)

7KY6 发表于 2018-1-14 12:51:48

支持楼主+1
页: [1]
查看完整版本: 大加减乘除 c源码 (测试)