傳說中的大數運算David

傳說中的實現除數比較複雜,我自己做的運算比他簡單

只是風格不一樣,回頭改掉他

#include <ctype.h>
#include <string.h>
#include "assert.h"
#include "calc.h"

#define T XP_T
#define BASE (1<<8)


unsigned long XP_fromint(int n, T z, unsigned long u)
{
 int i = 0;

 do
  z[i++] = u%BASE;
 while((u/=BASE)>0 && i < n);

 for( ; i < n; i++ )
  z[i++] = 0;
 return u;
}

unsigned long XP_toint(int n, T x)
{
  unsigned long u = 0;
  int i = (int) sizeof u;

  if( i > n )
   i = n;
  while( --i >= 0 )
   u = BASE*u + x[i];
  return u;
}


int XP_length( int n, T x)
{
 while( n>1 && x[n-1]==0 )
  n--;
 return n;
}

int XP_add( int n, T z, T x, T y, int carry )
{
 int i = 0;

 for( i=0; i<n; i++ )
 {
  carry += x[i] + y[i];
  z[i] = carry % BASE;
  carry /= BASE;
 }
 return carry;
}

int XP_sub( int n, T z, T x, T y, int borrow )
{
 int i;

 for( i=0; i<n; i++ )
 {
  int d = (x[i]+BASE) - borrow - y[i];
  z[i] = d % BASE;
  borrow = 1 - d/BASE ;
 }
 return borrow;
}

int XP_sum( int n, T z, T x, int y)
{
 int i;
 
 for( i = 0; i < n; i++ )
 {
  y += x[i];
  z[i] = y%BASE;
  y /= BASE;
 }
 return y;
}

int XP_diff( int n, T z, T x, int y)
{
 int i;

 for( i = 0; i < n; i++ )
 {
  int d = ( x[i] + BASE ) - y;
  z[i] = d%BASE;
  y /= 1- d/BASE;
 
 }
 return y;
}

int XP_neg( int n, T z, T x, int carry )
{
 int i;

 for( i = 0; i < n; i++ )
 {
  carry += (unsigned char)~x[i];
  z[i] = carry%BASE;
  carry /= BASE;
 }
 return carry;
}

int XP_mul( T z, int n, T x, int m, T y)
{
 int i, j, carryout = 0;

 for( i = 0; i < n; i++ )
 {
  unsigned carry = 0;
  for( j = 0; j < m; j++ )
  {
   carry += x[i]*y[j] + z[i+j];
   z[i+j] = carry%BASE;
   carry /= BASE;
  }

  for( ; j< n+m-1; j++ )
  {
   carry += z[i+j];
   z[i+j] = carry%BASE;
   carry /= BASE;
  }
  carryout |= carry;
 }
 return carryout;
}

int XP_product(int n, T z, T x, int y)
{
 int i;
 unsigned carry = 0;

 for( i = 0; i < n; i++ )
 {
  carry += x[i]*y;
  z[i] = carry%BASE;
  carry / BASE;
 }
 return carry;
}

 


//////////////////////////////////////////////////////////////////////////

int XP_div(int n, T q, T x, int m, T y, T r, T tmp)
{
 int nx = n, my = m;

 n = XP_length(n, x);
 m = XP_length(m, y);
 //只有一個元素
 if( m == 1 )
 {
  //並且除數爲0
  if(y[0]==0)
   return 0;
  //single digit division
  r[0] = XP_quotient(nx,q,x,y[0]);
  //fill zero
  memset(r+1, '/0', my-1);
 }
 else if( m > n)
 {
  memset( q, '/0', nx);
  memcpy(r, x, n);
  memset(r+n, '/0', my - n);
 }
 else
 {
  int k;
  unsigned char *rem = tmp, *dq = tmp+n+1;
  assert(2<=m && m<=n);
  memcpy( rem, x, n);
  rem[n] = 0;
  for( k = n - m; k >= 0; k-- )
  {
   int qk;
   {
    int i;
    assert(2<=m && m < k+m & k+m < n );
    {
     int km = k + m;
     unsigned long y2 = y[m-1]*BASE + y[m-2];
     unsigned long r3 = rem[km]*(BASE*BASE) + rem[km-1]*BASE+rem[km-2];
     qk = r3/y2;
     if(qk>=BASE)
      qk = BASE - 1;
    }
   }
   q[k] = qk;
   {
    int borrow;
    assert( 0 <= k && k <= k+m );
    borrow = XP_sub( m+1, &rem[k], &rem[k], dq, 0 );
    assert(borrow==0);
   }
  }
  memcpy(r, rem, m );
  {
   int i;
   for( i = n- m +1; i < nx; i++ )
    q[i] = 0;
   for( i = m; i < my; i++ )
    r[i] = 0;
  }
 }
 
}
/*
 * 這裏的數值計算David分析的比較透徹,除法
 *
 */
int XP_quotient(int n, T z, T x, int y)
{
 int i;
 unsigned carry = 0;

 for( i = n - 1; i >= 0; i--)
 {
  carry = carry*BASE+x[i];
  z[i] = carry/y;
  carry %= y;
 }
 return carry;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章