Неправильный ответ из алгоритма spigot - PullRequest
0 голосов
/ 06 апреля 2019

Я кодирую алгоритм spigot для отображения цифр числа пи в ada, но мой вывод неверен, и я не могу понять, почему

Я пытался связываться с диапазоном своих циклов и различнымиспособы вывода моих данных, но ничто не работало должным образом

with ada.integer_text_io; use ada.integer_text_io;
with Ada.Text_IO; use Ada.Text_IO;

procedure Spigot is
    n : constant Integer := 1000;
    length : constant Integer := 10*n/3+1;
    x,q,nines,predigit :Integer :=0;
    a: array (0..length) of Integer;

begin
    nines:=0;
    predigit:=0;

    for j in 0..length loop
        a(j):=2;
    end loop;

    for j in  1..n loop
        q:=0;
        for i in reverse 1..length loop
            x:=10*a(i) + q*i;
            a(i):= x mod (2*i-1);
            q:= x/(2*i-1);
        end loop;

        a(1):= q mod 10;
        q:=q/10;

        if q = 9 then
            nines:=nines+1;
        elsif q = 10 then
            put(predigit+1);
            for k in 0..nines loop
                put("0");
            end loop;
            predigit:=0;
            nines:=0;
        else
            put(predigit);
            predigit:=q;
            if nines/=0 then
                for k in 0..nines loop
                    put("9");
                end loop;
                nines:=0;
            end if;      
        end if;   
    end loop;
    put(predigit);
end Spigot;

, поэтому они просто должны отображаться в 0 3 1 4 1 5 9 2 6 5 3 5 8 9 ... но вывод, который я получаю, равен 0 31 4 1 599 2 6 5 3 5 89 ... это должна быть только 1 цифра за раз, а также выведенные значения для pi не совсем корректны

Ответы [ 2 ]

2 голосов
/ 06 апреля 2019

Я недостаточно хорошо знаю алгоритм, чтобы говорить о том, почему цифры отключены, но я заметил некоторые проблемы:

  1. Ваш массив определен с границами 0 .. Длина, что даст вам 1 дополнительный элемент
  2. В вашем цикле, который выполняет вычисления, вы выполняете цикл с 1..length, что нормально, но вы не корректируете переменную i последовательно. Индексы массива должны быть на единицу меньше, чем i, используемый в реальных вычислениях (имейте в виду, что они все равно должны быть правильно в границах вашего массива). Например

        x:=10*a(i) + q*i;
    

    должно быть либо

        x:=10*a(i-1) + q*i;
    

    или

        x:=10*a(i) + q*(i+1);
    

    в зависимости от того, как вы решите, каковы границы вашего массива. Это относится к нескольким строкам в вашем коде. Посмотрите это Поток Stackoverflow

  3. Вы назначаете A (1), когда ваш массив начинается с 0

  4. Ваши циклы для вывода "0" и "9" должны быть либо 1..length, либо 0 .. length-1
  5. Когда вы печатаете цифры, используя Integer_Text_IO.Put, вам нужно указать ширину 1, чтобы избавиться от пробелов

Может быть, больше, это все, что я видел.

2 голосов
/ 06 апреля 2019

Я думаю, вы переводите этот ответ .

Вы должны быть осторожнее с вашими индексами и диапазонами петель; например, вы перевели

for(int i = len; i > 0; --i) {
  int x  = 10 * A[i-1] + q*i;
  A[i-1] = x % (2*i - 1);
  q = x / (2*i - 1);
}

в

for i in reverse 1..length loop
    x:=10*a(i) + q*i;
    a(i):= x mod (2*i-1);
    q:= x/(2*i-1);
end loop;

Диапазоны петель одинаковы. Но в строке seocnd код C использует A[i-1], а ваш - a(i); аналогично в третьей строке.

Позже, для

  for (int k = 0; k < nines; ++k) {
    printf("%d", 0);
  }

у вас есть

  for k in 0..nines loop
      put("0");
  end loop;

, в котором цикл C работает от 0 до nines - 1, а ваш - от 0 до nines. Таким образом, вы производите на 0 больше, чем должны (а позже и на 1026 * с).

Кроме того, вы должны использовать put (predigit, width=> 0).

...