Dziwne zachowanie funkcji liczącej n!

0

Oto dwie implementacje algorytmu liczącego n!:

  1. z książki:
function Silnia(n: Integer): Integer;
begin
  if n <= 0 then
    Result := 1
  else
    Result := Silnia(n-1) * n;
end;
  1. moja:
function MojaSilnia(n: Integer): Integer;
begin
  if n = 0 then
    Result := 1
  else if n = 1 then
    Exit
  else
    Result := MojaSilnia(n-1) * n;
end;

Mimo, że kompilator wywala ostrzeżenie: Return value of function 'MojaSilnia' might be undefined, obie liczą poprawnie do wartości 12!, ponieważ większe wartości dają wyniki wykraczające poza zakres Integer. Żeby policzyć, np. 15! można zrobić małą modyfikację:

function Silnia(n: Integer): Int64;
begin
  if n <= 0 then
    Result := 1
  else
    Result := Silnia(n-1) * n;
end;
function MojaSilnia(n: Integer): Int64;
begin
  if n = 0 then
    Result := 1
  else if n = 1 then
    Exit
  else
    Result := MojaSilnia(n-1) * n;
end;

Kompilator nadal wyrzuca w/w ostrzeżenie i zaczynają się dziać dziwne (?) rzeczy. Pierwsza funkcja liczy poprawnie do wartości 19!, bo na tyle wystarcza typ Int64, druga „wymyśla” takie bzdury, że głowa pęka. Może mi ktoś powiedzieć, co jest grane?

0
else if n = 1 then
    Exit

Co ta funkcja niby ma zwrocic dla n==1? Komputer to nie wrozka.

0

No dobra. Tylko czemu obie funkcje liczą dobrze gdy zwracają Integer. Gdy zwracają Int64 to druga się sypie? Kiedyś wyczytałem, że tak należy pisać kod by nie pokazywały się ostrzeżnia, czy komunikaty kompilatora, bo może to spowodować dziwne zachowanie programu. Czy jest to z tym związane? Czy może z tym, co pisze Help: "An integer type represents a subset of the whole numbers. The generic integer types are Integer and Cardinal; use these whenever possible, since they result in the best performance for the underlying CPU and operating system.[...]"

0

Dlaczego? Bo może i zwracasz int64 ale w kodzie nie operujesz na tego typu liczbach.
Tak, jak zauważył Wolverine, dla n < 2 funkcja ma zwracać 1.
I jeszcze jedno, miło by było użyć rekurencji ogonowej.

0

fakt pozostaje faktem, że gdy n będzie się równało 1 to Rezult = "dupa" ? bo nie widze zwrotu żadnej wartości...

// jesteś trzecią osobą, która to napisała, czytaj może uważnie wszystkie posty? (dop. deus)

"nie liczy sie jak to bedzie zrobione, wazne zeby bylo zrobione" :)

0
york_daro napisał(a)

fakt pozostaje faktem, że gdy n będzie się równało 1 to Rezult = "dupa" ? bo nie widze zwrotu żadnej wartości...

Dziwne zrządzenie losu chciało że dla 0! zwraca 1, 1! zwraca 1, 2! – 2, 3! – 6, 4! – 24, 5! – 120 ... 12! – 479001600, ale wtedy i tylko w tedy, gdy funkcja zwraca typ Integer. Gdy zwraca typ Int64 wyniki są zatrważające. Teraz już wiem, że kołomyję robiło to nieszczęsne

if n = 1 then
    Exit;

po małej modyfikacji:

function MojaSilnia(n: Integer): Integer; // function MojaSilnia(n: Integer): Int64
begin
  if n = 0 then
    Result := 1
  else if n = 1 then
  begin
    Result := 1;
    Exit;
  end
  else
    Result := Silnia(n-1) * n;
end;

co sprowadza się do prostszego zapisu

function MojaSilnia(n: Integer): Integer; //function MojaSilnia(n: Integer): Int64
begin
  if n <= 1 then
    Result := 1
  else
    Result := Silnia(n-1) * n;
end;

ostrzeżenie: Return value of function 'MojaSilnia' might be undefined nie pojawia się i funkcja liczy poprawnie <ort>nie zależnie</ort> od tego czy zwraca typ Integer czy Int64.

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