Программа факторизации Pascal / Python

1

Я сделал две программы, чтобы найти простые коэффициенты числа, один в python и один в pascal. Я бы хотел факторизовать 600851475143; программа python факторизует ее мгновенно. Однако, паскаль не заканчивается в разумные сроки. Это связано с другим языком программирования или с тем, как я закодировал его в Паскале? Я использовал рекурсию в python, но не в pascal. Почему программа pascal также не выполняется мгновенно?

питон:

def findLowestFactor(num, factors=None):
    if factors:
        start = factors[-1]
    else:
        start = 2
    for i in range(start, int(num)):
        if num%i == 0:
            return i
    else:
        return False


def findPrimeFactors(num, factors=None):
    if factors is None:
        factors = []
    factor = findLowestFactor(num, factors)
    if factor:
        factors.append(factor)
        findPrimeFactors(num/factor, factors)
        return factors
    else: 
        factors.append(int(num))
        return factors


if __name__ == "__main__":
    while True:
        num = int(input("Please enter a number: "))
        factors = findPrimeFactors(num)
        print(*factors)

Паскаль:

program Primes;

var
  input:string;
  num:integer;
  error:integer;
  factor:integer;
  factors:array of integer;
  found: boolean;
  start:integer;
  x:integer;


begin
  writeln(600851475143);
  (*Repeat untill exit*)
  while true do
  begin
    (*Repeat untill valid input*)
    repeat
    write('Enter a number: ');
    readln(input);
    val(input, num, error);
    if error = 1 then
      writeln('Not an integer');
    until error = 0;

    writeln;

    (*set up list*)
    SetLength(factors, 0);
    factor := 0;
    found := false;
    (*while num is not prime*)
    while found = false do
    begin
      (*start from largest factor found for efficiency*)
      if length(factors) > 0 then
        start := factors[length(factors)-1]
      else
        start := 2;
      (*loop through numbers from number in start var to current num*)
      for factor := start to num do
      begin
        (*if there are no more factors*)
        if num / factor = 1 then
          begin;
            (*add final factor to list*)
            SetLength(factors, length(factors)+1);
            factors[length(factors)-1] := factor;
            (*break out of the loop*)
            found := True;
          end
        (*if factor is found*)
        else if num mod factor = 0 then
          begin
            (*divide num by found factor*)
            num := num div factor;
            (*add the factor*)
            SetLength(factors, length(factors)+1);
            factors[length(factors)-1] := factor;
            (*break for efficiency*)
            Break;
          end;


      end;
    end;

    write('Prime Factors: ');
    for x:= 0 to length(factors)-1 do
      write(factors[x], ' ');
    writeln;
    writeln;

  end;

end. 
  • 0
    Трудно сказать. Какой Паскаль ты использовал? Кроме того, код Python хорошо структурирован, в то время как код Pascal представляет собой почти один отдельный блок. Подход, кажется, тоже другой, поэтому вполне может быть объяснен этой разницей. Также обратите внимание, что 600851475143 больше 32 бит, поэтому, если целое число составляет 32 бита в Паскале, оно может работать не так, как ожидалось. Python, вероятно, использует правильный тип данных в зависимости от числа, которое вы ему даете. Так что может быть несколько факторов.
  • 0
    FWIW, вместо Integer, попробуйте использовать Int64 для соответствующих переменных в Pascal.
Теги:
pascal
factorization

1 ответ

4
Лучший ответ

Я перевел код Python на Pascal. Я использовал Delphi, но он тоже должен компилироваться в FreePascal. Он мгновенно возвращается:

type
  TIntArray = array of Integer; // Delphi: TArray<Integer>;

function findLowestFactor(num: Int64; factors: TIntArray): Integer;
var
  start: Integer;
  i: Int64;
begin
  if Length(factors) > 0 then
    start := factors[High(factors)]  // factors[-1] in Python, i.e. last entry.
  else
    start := 2;
  i := start;
  while i < num do        // Int64 can not be used as index in for-loop... 
  begin                   // ... so I use while loop.
    if num mod i = 0 then // Python: if num % i == 0:
      Exit(i);            // return i
    Inc(i);
  end;
  Exit(0);
end;

procedure findPrimeFactors(num: Int64; var factors: TIntArray);
var
  factor: Integer;
begin
  factor := findLowestFactor(num, factors);
  if factor > 0 then
  begin 
    // Delphi: factors := factors + [factor];
    SetLength(factors, Length(factors) + 1);
    factors[High(factors)] := factor;

    findPrimeFactors(num div factor, factors);
  end
  else
  begin
    // Delphi: factors := factors + [Integer(num)];
    SetLength(factors, Length(factors) + 1);
    factors[High(factors)] := Integer(num);
  end;
end;

const
  testValue: Int64 = 600851475143;

var
  factors: TIntArray;
  i: Integer;
  result: Int64;

begin
  // Instead of user input, I use the testValue above.
  Writeln('test value: ', testValue);
  findPrimeFactors(testValue, factors);
  result := 1;
  for i in factors do
  begin
    Write(i:8);
    result := result * i;
  end;
  Writeln;
  Writeln('multiplied: ', result);
  Readln;
end.

Обратите внимание, что мне пришлось использовать Int64 в некоторых местах. Я предполагаю, что Python делает это автоматически, но не Pascal. Возможно, использование целых чисел в некоторых местах сделало ваш код настолько медленным.

Я пропустил пользовательские части ввода кода (Readln и т.д.), Просто использовал постоянное значение, которое вы дали. Но, как я уже сказал, он возвращается мгновенно, с правильными значениями (см. Результат переменной).

  • 0
    Спасибо за ваш ответ. Да, проблема была в том, что я не использовал Int64, поскольку я новичок в Паскале. Я прочитаю и попытаюсь понять вашу версию на Pascal, используя рекурсию. Я пытался перевести это сам, но в Паскале пока не был достаточно хорош. :)
  • 0
    Обратите внимание, что я написал это в Delphi. Там вместо строки SetLength () и строки после этого вы можете просто сделать: factors := factors + [factor]; , Но я не думаю, что это возможно в других реализациях Паскаля.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню