Iloczyn potęg liczb pierwszych.

0

Witam serdecznie

Z góry zaznaczam że dopiero rozpoczynam przygodę z programowaniem, więc proszę o wyrozumiałość
Piszę program zaliczeniowy z Delphi. Ma on przedstawiać liczbę w postaci iloczynu potęg liczb pierwszych. O ile rozkład liczby na czynniki pierwsze nie przysparza mi większych problemów, to pogrupowanie czynniku na wzór np. 2332 zamiast 2223*3 jest już dla mnie sporym problemem

Program, który tutaj przedstawię kompiluje się, debugger nie pokazuje żadnych błędów. Uruchamia się, lecz kiedy wpiszę liczbę do Pola Edit1 i chcę już wykonać obliczenia, po wduszeniu button1 następuje zawieszenie programu. Nie mam pojęcia gdzie popełniłem błąd i prosiłbym o łopatologiczne wyjaśnienie mi mojej pomyłki

Oto kod

unit Unit1;

interface

uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Math, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
Edit1: TEdit;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
i, j, k, a, e, temp: Integer;
tab: array of Integer;
napis: String;
pierwsza: Boolean;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
a:=StrToInt(Edit1.Text);
e:=floor(sqrt(a))+1;
SetLength(tab, e);
temp:=a;

j:=0;
while j<e do
begin
tab[i]:=0;
end;

i:=3;
if a=2 then tab[a]:=1
else
begin
while i<=e do
begin
if (a mod i) = 0 then
begin
tab[i]:=tab[i]+1;
a:=a div i;
end
else i:=i+2;
end;
end;

pierwsza:=true;
i:=3;
while i<=e do
begin
if tab[i]<>0 then
begin
pierwsza:=false;
Break;
end;
end;

j:=2;
if pierwsza=true then napis:=IntToStr(temp)
else
begin
while j<=e do
begin
if (tab[j]>0) then
begin
if tab[j]=1 then napis:=napis+IntToStr(j)
else napis:=napis+IntToStr(j)+'^'+IntToStr(tab[j]);
if i<>e-1 then napis:=napis+'*';
end;
j:=j+1;
end;
end;
Memo1.Lines.Add(napis);
end;

end.

Z góry dziękuję za wszelką pomoc

0

Może sformatuj kod po ludzku.

0
unit Unit1;

interface

uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Math, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
   TForm1 = class(TForm)
   Button1: TButton;
   Memo1: TMemo;
   Edit1: TEdit;

procedure Button1Click(Sender: TObject);

private
   { Private declarations }
public
   { Public declarations }
end;

var
   Form1: TForm1;
   i, j, k, a, e, temp: Integer;
   tab: array of Integer;
   napis: String;
   pierwsza: Boolean;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
   begin
       a:=StrToInt(Edit1.Text);
       e:=floor(sqrt(a))+1;
       SetLength(tab, e);
       temp:=a;

       j:=0;
       while j<e do
             begin
                tab[i]:=0;
             end;


       i:=3;
       if a=2 then 
                    tab[a]:=1
                else
                     begin
                          while i<=e do
                                begin
                                       if (a mod i) = 0 then
                                                               begin
                                                                   tab[i]:=tab[i]+1;
                                                                   a:=a div i;
                                                                end
                                                             else i:=i+2;
                                 end;
                     end;


    pierwsza:=true;
    i:=3; 
    while i<=e do
                      begin
                          if tab[i]<>0 then
                                             begin
                                                   pierwsza:=false;
                                                    Break;
                                             end;
                      end;


   j:=2;
   if pierwsza=true then napis:=IntToStr(temp)
                          else
                               begin
                                 while j<=e do
                                     begin
                                          if (tab[j]>0) then
                                                               begin
                                                                    if tab[j]=1 then napis:=napis+IntToStr(j)
                                                                                    else napis:=napis+IntToStr(j)+'^'+IntToStr(tab[j]);
                                                                                     if i<>e-1 then napis:=napis+'*';
                                                                end;
   j:=j+1;
                                      end;
                                end;
Memo1.Lines.Add(napis);
end;

end. 
0
j:=0;
while j<e do
begin
  tab[i]:=0;
end;

Prawdopodobnie tu leży błąd bo j będzie zawsze mniejsze od e więc pętla jest nieskończona. Nie wgłębiałem się aż tak dokładnie w kod więc nie mam pojęcia jaki skok w pętli jest ci potrzeby ale albo zamień tą pętle na pętle for j := 0 to e do albo na końcu w bloku begin end dodaj inc(j);

0

for j:=0 to e do
begin
tab[i]:= 0;
end;

Niestety nie rozwiązuje to problemu działania aplikacji.

0
while j<=e do
                                     begin
                                          if (tab[j]>0) then
                                                               begin
                                                                    if tab[j]=1 then napis:=napis+IntToStr(j)
                                                                                    else napis:=napis+IntToStr(j)+'^'+IntToStr(tab[j]);
                                                                                     if i<>e-1 then napis:=napis+'*';
                                                                end;
   j:=j+1;
                                      end;

tutaj też j jest zawsze mniejsze od e a nigdy nie będzie równe lub większe e. Przemyśl wszystkie pętle i warunki.

0

Ja proponuję tak:

Kod dla ludzi:

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Math,
  System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    Edit1: TEdit;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  i, j, k, a, e, temp: integer;
  tab: array of integer;
  napis: string;
  pierwsza: boolean;

implementation

 {$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  a := StrToInt(Edit1.Text);
  e := floor(sqrt(a)) + 1;
  SetLength(tab, e);
  temp := a;

  j := 0;
  while j < e do
  begin
    tab[i] := 0;
  end;


  i := 3;
  if a = 2 then
    tab[a] := 1
  else
  begin
    while i <= e do
    begin
      if (a mod i) = 0 then
      begin
        tab[i] := tab[i] + 1;
        a := a div i;
      end
      else
        i := i + 2;
    end;
  end;


  pierwsza := True;
  i := 3;
  while i <= e do
  begin
    if tab[i] <> 0 then
    begin
      pierwsza := False;
      Break;
    end;
  end;


  j := 2;
  if pierwsza = True then
    napis := IntToStr(temp)
  else
  begin
    while j <= e do
    begin
      if (tab[j] > 0) then
      begin
        if tab[j] = 1 then
          napis := napis + IntToStr(j)
        else
          napis := napis + IntToStr(j) + '^' + IntToStr(tab[j]);
        if i <> e - 1 then
          napis := napis + '*';
      end;
      j := j + 1;
    end;
  end;
  Memo1.Lines.Add(napis);
end;

end.

A ten kod dla pytacza (czytaj karne cośtam za jakieśtam formatowanie):

UNIT UNIT1;INTERFACE USES WINAPI.WINDOWS,WINAPI.MESSAGES,SYSTEM.SYSUTILS,SYSTEM.
MATH,SYSTEM.VARIANTS,SYSTEM.CLASSES,VCL.GRAPHICS,VCL.CONTROLS,VCL.FORMS,VCL.DIALOGS
,VCL.STDCTRLS;TYPE TFORM1=CLASS(TForm)BUTTON1:TBUTTON;MEMO1:TMEMO;EDIT1:TEDIT;PROCEDURE
BUTTON1CLICK(SENDER:TOBJECT);PRIVATE PUBLIC END;VAR FORM1:TFORM1;I,J,K,A,E,TEMP:INTEGER
;TAB:ARRAY OF INTEGER;NAPIS:STRING;PIERWSZA:BOOLEAN;IMPLEMENTATION {$R *.dfm}PROCEDURE
TFORM1.BUTTON1CLICK(SENDER:TOBJECT);BEGIN A:=STRTOINT(EDIT1.TEXT);E:=FLOOR(SQRT(A
))+1;SETLENGTH(TAB,E);TEMP:=A;J:=0;WHILE J<E DO BEGIN TAB[I]:=0;END;I:=3;IF A=2 THEN
TAB[A]:=1 ELSE BEGIN WHILE I<=E DO BEGIN IF(A MOD I)=0 THEN BEGIN TAB[I]:=TAB[I]+
1;A:=A DIV I;END ELSE I:=I+2;END;END;PIERWSZA:=TRUE;I:=3;WHILE I<=E DO BEGIN IF TAB
[I]<>0 THEN BEGIN PIERWSZA:=FALSE;BREAK;END;END;J:=2;IF PIERWSZA=TRUE THEN NAPIS:=
INTTOSTR(TEMP)ELSE BEGIN WHILE J<=E DO BEGIN IF(TAB[J]>0)THEN BEGIN IF TAB[J]=1 THEN
NAPIS:=NAPIS+INTTOSTR(J)ELSE NAPIS:=NAPIS+INTTOSTR(J)+'^'+INTTOSTR(TAB[J]);IF I<>
E-1 THEN NAPIS:=NAPIS+'*';END;J:=J+1;END;END;MEMO1.LINES.ADD(NAPIS);END;END.

Program, który tutaj przedstawię kompiluje się, debugger nie pokazuje żadnych błędów.

Debugger nie służy tylko do wyświetlania błędów, proponuję poczytać o bp i watch a następnie użyć tych narzędzi aby wykryć źródło niepowodzeń algorytmu.

0

I powinien być jeszcze karny k.... za brak tagu, nazwę języka w temacie - a nie właśnie w tagu, a do tego dopisuwanie jakieś dopiski typu "problem". Ludzie myslą, że jak dopiszą w temacie wątku na końcu "preblem" albo gdzieś w nim "pomocy" to zaraz każdy rzuci się by im odpowiedzieć jakby ich wątek był najważniejszy na Świecie. Tym razem wszystko poprawiłem. Następnym razem jednak nie będę się chyba zastanawiał nad nagrodą - Koszem.

0

Program sprawdziłem po poprawkach i tak nie działa, ktoś ma pomysł jak go poprawić bo ja wymiękam.

0

DEBUGGER!

0

Dziękuje wszystkim za odpowiedzi. Poradziłem sobie z problemem stosując zupełnie inny algorytm. Załączam kod dla ciekawych.

unit Z1;

interface

uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
Edit1: TEdit;
Label1: TLabel;
Label2: TLabel;
Edit2: TEdit;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
i, j, a, a1, temp, d: integer;
tab: array of integer;
napis: string;
gwiazdka :string[1];
pierwsza: boolean;
h,m,s,ms:word;
start,stop:TDateTime;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
Memo1.Clear;
a:=StrToInt(Edit1.Text);
start:=Time;
a1:=a+1;
SetLength(tab, a1);
temp := a;
i := 2;
begin
while i <= a do
begin
while (a mod i) = 0 do
begin
tab[i] := tab[i] + 1;
a := a div i;
end;
i:= i + 1;
end;
end;
i:=0;
while i<=temp do
begin
if tab[i]>0 then
begin
if tab[i]=1 then
begin
napis:=napis+ IntToStr(i)+'';
i:=i+1;
end
else
begin
napis:=napis+IntToStr(i)+'^'+IntToStr(tab[i])+'
';
i:=i+1;
end;
end
else
i:=i+1;
end;
d:= length(napis);
gwiazdka:=Copy(napis,d,1);
if gwiazdka='*' then
delete(napis,d,1);
Memo1.Lines.Add('Podana liczba w postaci iloczynu potęg liczb pierwszych: '+napis);
stop:=Time;
DecodeTime(stop-start,h,m,s,ms);
Edit2.Text:=IntToStr(ms)+'ms';
end;

end.

0

Strasznie skomplikowane i niezbyt wydajne. Wystarczy tyle :D

var N:Cardinal;
var I,K,Pow,Size:Integer;
var S:String;
var Pr:array of Boolean;
begin
  Write('podaj liczbe: ');
  ReadLn(N);
  Size:=Floor(Sqrt(N));
  SetLength(Pr,Size+1);
  SetLength(S,0);
  for I:=0 to 1 do Pr[I]:=false;
  for I:=2 to Size do Pr[I]:=true;
  for I:=2 to Size do
  begin
    if Pr[I] then
    begin
      K:=(I)shl(1);
      while K<=Size do
      begin
        Pr[K]:=false;
        Inc(K,I);
      end;
      Pow:=0;
      while ((N)mod(I))=0 do
      begin
        N:=(N)div(I);
        Inc(Pow);
      end;
      if Pow>0 then
      begin
        S:=S+IntToStr(I);
        if Pow>1 then S:=S+'^'+IntToStr(Pow);
        S:=S+'*';
      end;
    end;
    if I*I>N then Break;
  end;
  if N>1 then S:=S+IntToStr(N) else SetLength(S,Length(S)-1);
  WriteLn(S);
end.

1 użytkowników online, w tym zalogowanych: 0, gości: 1