Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > Перевод кода с С++ на C#


Автор: yarus88 16.4.2009, 10:02
Не получается правильно перевести код с С++ на C#

Вот есть деление длинного числа на длинное на С++ 
Код

// Q = A/B, R=A%B 
void Div(const BigInt &A, BigInt &B, BigInt &Q, BigInt &R) { 
 // Вырожденный случай 1. Делитель больше делимого. 
  if ( A.Size < B.Size ) {   
  Q.zero(); 
  R=A; 
  return; 
 } 
// Вырожденный случай 2. Делитель – число базового типа. 
  if ( B.Size == 1) {    
    SDiv ( A, B.Coef[0], Q, R.Coef[0]); 
  R.Size = 1; 
  return; 
 } 
  // Создать временный массив U, равный A 
 // Максимальный размер U на цифру больше A, с учетом  
 // возможного удлинения A при нормализации 
 BigInt U(A.Size+1); U = A; U.Coef[A.Size]=0;  
 
// Указатели для быстрого доступа 
 short *b=B.Coef, *u=U.Coef, *q=Q.Coef; 
  
long n=B.Size, m=U.Size-B.Size; 
 long uJ, vJ, i;     
 long temp1, temp2, temp; 
short scale;   // коэффициент нормализации 
 short qGuess, r;            // догадка для частного и соответствующий остаток 
 short borrow, carry;   // переносы 
// Нормализация 
 scale = BASE / ( b[n-1] + 1 );  
 if (scale > 1) {     
   SMul (U, scale, U); 
   SMul (B, scale, B); 
 } 
// Главный цикл шагов деления. Каждая итерация дает очередную цифру частного. 
// vJ - текущий сдвиг B относительно U, используемый при вычитании, 
// по совместительству - индекс очередной цифры частного. 
// uJ – индекс текущей цифры U 
 for (vJ = m, uJ=n+vJ; vJ>=0; --vJ, --uJ) { 
   qGuess = (u[uJ]*BASE + u[uJ-1]) / b[n-1]; 
   r = (u[uJ]*BASE + u[uJ-1]) % b[n-1]; 
  // Пока не будут выполнены условия (2) уменьшать частное. 
   while ( r < BASE) {  
   temp2 = b[n-2]*qGuess; 
     temp1 = r*BASE + u[uJ-2]; 
     if ( (temp2 > temp1) || (qGuess==BASE) ) { 
    // условия не выполнены, уменьшить qGuess  
    // и досчитать новый остаток 
    --qGuess; 
    r += b[n-1]; 
   } else break; 
  } 
 // Теперь qGuess - правильное частное или на единицу больше q   
 // Вычесть делитель B, умноженный на qGuess из делимого U, 
 // начиная с позиции vJ+i 
 carry = 0; borrow = 0;  
 short *uShift = u + vJ; 
 // цикл по цифрам B 
 for (i=0; i<n;i++) { 
  // получить в temp цифру произведения B*qGuess 
   temp1 = b[i]*qGuess + carry;   
   carry = temp1 / BASE; 
   temp1 -= carry*BASE;        
  // Сразу же вычесть из U 
   temp2 = uShift[i] - temp1 + borrow;   
   if (temp2 < 0) { 
   uShift[i] = temp2 + BASE; 
   borrow = -1; 
  } else { 
   uShift[i] = temp2; 
   borrow = 0; 
  } 
 } 
// возможно, умноженое на qGuess число B удлинилось. 
 // Если это так, то после умножения остался  
// неиспользованный перенос carry. Вычесть и его тоже. 
    temp2 = uShift[i] - carry + borrow; 
    if (temp2 < 0) { 
      uShift[i] = temp2 + BASE; 
   borrow = -1; 
  } else { 
   uShift[i] = temp2; 
   borrow = 0; 
  } 
   
 
  // Прошло ли вычитание нормально ? 
    if (borrow == 0) {    // Да, частное угадано правильно 
   q[vJ] = qGuess;  
 
  } else { // Нет, последний перенос при вычитании borrow = -1, 
    // значит, qGuess на единицу больше истинного частного 
   q[vJ] = qGuess-1; 
  // добавить одно, вычтенное сверх необходимого B к U 
  carry = 0; 
   for (i=0; i<n; i++) { 
     temp = uShift[i] + b[i] + carry; 
   if (temp >= BASE) { 
    uShift[i] = temp - BASE; 
    carry = 1; 
   } else { 
    uShift[i] = temp; 
    carry = 0; 
   } 
  } 
   uShift[i] = uShift[i] + carry - BASE; 
 } 
 // Обновим размер U, который после вычитания мог уменьшиться 
 i = U.Size-1; 
 while ( (i>0) && (u[i]==0) ) i--; 
 U.Size = i+1; 
 } 
 // Деление завершено ! 
 
 // Размер частного равен m+1, но, возможно, первая цифра - ноль. 
  while ( (m>0) && (q[m]==0) ) m--; 
  Q.Size = m+1; 
  
 // Если происходило домножение на нормализующий множитель –  
 // разделить на него. То, что осталось от U – остаток. 
  if (scale > 1) { 
  short junk;  // почему-то остаток junk всегда будет равен нулю… 
    SDiv ( B, scale, B, junk); 
    SDiv ( U, scale, R, junk); 
  } else R=U;   


Не получается правильно на C# это сделать...
у меня есть класс BigInt
Код

static int BASE = 10;
        public class BigInt
        {
            public int len; //длинна числа
            public int[] digs = new int[1000];
        }


есть функции SMul (умножение длинного на короткое) и SDiv (деление длинного на короткое)
Код

static void SMul(BigInt NumberA, int NumberB, BigInt Answer)
        {
            int i, temp;
            int carry = 0;
            for (i = 0; i < NumberA.len; i++)
            {
                temp = NumberA.digs[i] * NumberB + carry;
                carry = temp / BASE;
                Answer.digs[i] = temp - carry * BASE;
            }
            if (carry == 1)
            {
                Answer.digs[i] = carry;
                i++;
            }
            Answer.len = i;
        }


Код

static void SDiv(BigInt NumberA, int NumberB, BigInt Answer, BigInt Rest)
        {
            int i, temp;
            Rest.digs[0] = 0;
            Rest.len = 1;            
            for (i = NumberA.len - 1; i >= 0; i--)
            {
                temp = Rest.digs[0] * BASE + NumberA.digs[i];
                Answer.digs[i] = temp / NumberB;
                if ((Answer.digs[i] != 0) && (Answer.len < i))
                {
                    Answer.len = i + 1;
                }
                Rest.digs[0] = temp - Answer.digs[i] * NumberB;                
            }            
        }


Помогите с делением длинного на длинное.. smile 3 день парюсь никак не получится!!!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)