[TP] silnia

0

Witam !
Czy ktos moglby mi pomoc w napisaniu programu obliczajacego wartosc funkcji silnia dla zadanego argumentu ?
Program powinien pytac uzytkownika o liczbe dla jakiej pragniemy obliczyc funkcje silnia, a nastepnie wyswietlac wynik ...--
pozdro_4_all

0

wynik:=1;
For i:=1 to liczba then
wynik:=wynik*i;

Ale przy kilkunastu juz padnie ;]
Poza zakres..--Pamietaj że święto zmarłych stanie się także twoim świętem.

0

werw0e napisał:
wynik:=1;
&gtFor i:=1 to liczba then
&gt wynik:=wynik*i;
&gt
&gtAle przy kilkunastu juz padnie ;]
&gtPoza zakres..

po pierwsze: for i:=2 to liczba (zawsze jeden obrot petli mniej)

po drugie: trzeba uzyc duzego zmiennoprzecinkowego typu (w Delphi Int64 wywala sie powyzej 20, a double dopiero powyzej 170).

--
Pawel {Delphi 6 Personal}

Po pierwsze: naciśnij F1

0

Witam !
[hurra] Dziekuje bardzo za odpowiedz !
Dodam jeszcze ze nalezy sprawdzac, czy wprowadzona liczba jest poprawna (wartosc funkcji silnia jest okreslona dla zbioru liczb naturalnych). Nalezy przetestowac zachowanie programu dla roznych typow danych, w ramach ktorych moze byc obliczny wynik, tj. dla ShortInt, Integer, LongInt, Byte, Word.
LOL Nie spodziewalem sie tak szybkiej reakcji

pozdro_4_all--
pozdro_4_all

0

pq napisał:
&gtpo pierwsze: for i:=2 to liczba (zawsze jeden obrot petli mniej)
Tak??
A mi jakos nie chce dzialac jak wprowadze liczbe naturalna 1 ;P

&gtpo drugie: trzeba uzyc duzego zmiennoprzecinkowego typu (w Delphi Int64 wywala sie powyzej 20, a double dopiero powyzej 170).

TP=Turbo Pascal (tak mysle)
jak tak to przyklad z Delphi jest nie trafiony :)--Pamietaj że święto zmarłych stanie się także twoim świętem.

0

werw0e napisał:
pq napisał:
&gt&gtpo pierwsze: for i:=2 to liczba (zawsze jeden obrot petli mniej)
&gtTak??
&gtA mi jakos nie chce dzialac jak wprowadze liczbe naturalna 1 ;P
&gt
Racja [wstyd]

&gt&gtpo drugie: trzeba uzyc duzego zmiennoprzecinkowego typu (w Delphi Int64 wywala sie powyzej 20, a double dopiero powyzej 170).
&gt
&gtTP=Turbo Pascal (tak mysle)
&gtjak tak to przyklad z Delphi jest nie trafiony :)

Pewnie bedzie Real w TP, ale nie poniewaz nie znam dokladnie zmiennoprzecinkowych typow w TP dalem przyklad z Delphi. Przyklad jest trafiony, bo pokazuje jak szybko wywalaja sie typy staloprzecinkowy i zmiennoprzecinkowy o tym samym rozmiarze 8 bajtow.--Pawel {Delphi 6 Personal}

Po pierwsze: naciśnij F1

0

tomex napisał:
wartosc funkcji silnia jest okreslona dla zbioru liczb naturalnych

Gdzieś widziałem wzór na wersję silni dla liczb rzeczywistych (of koz standardowa definicja wtedy odpada).--Vogel [Delphi 6 PE]

Life is just a dream, you know...
[Cowboy Bebop]

0

Vogel napisał:
&gtGdzieś widziałem wzór na wersję silni dla liczb rzeczywistych (of koz standardowa &gtdefinicja wtedy odpada).

Witam !
Na wstepie; wielkie dzieki !
Funkcja silnia jest zdefiniowana w postaci nastepujacej zaleznosci rekurencyjnej:
0!=0
1!=0!*1=1
2!=1!*2=2
...
n!=(n-1)!*n (n&gt0)

Cala zaleznosc mozna tez zapisac jako (wersja iteracyjna):

n!=1234...*(n-1)*n

btw
Dla kazdego typu nalezy sprawdzic, dla jakiej najwiekszej liczby wejsciowej program wyswietla poprawny wynik i jakie wyniki sa wyswietlane dla liczb wiekszych. Swoje wnioski zawrzec w postaci komentarzy w pliku z rozwiazaniem.
Otrzymane wyniki nalezy wykorzystac do zabezpieczenia programu przed obliczaniem niepoprawnych wartosci. W tej sytuacji, po wpisaniu zbyt duzej liczby wejsciowej, program powinien wyswietlic odpowiedni komunikat, informujacy o niemozliwosci wykonania obliczen (nalezy dobrac typ danych umozliwiajacy nam obliczanie najwiekszej wartosci funkcji silnia).

pozdro_4_all--
pozdro_4_all

0

tomex napisał:
&gtFunkcja silnia jest zdefiniowana w postaci nastepujacej zaleznosci rekurencyjnej:
&gt0!=0
&gt1!=0!*1=1

Co ty za gupoty opowiadasz??
0!=0 tak wiec
1!=01
0
1 to jest 0 (chcialem uzyc wykrzyknika ale wiadomo)
0!=1 --Pamietaj że święto zmarłych stanie się także twoim świętem.

0

Wiem jak zrobić progsa (chociażby w TP7 ), który liczy silnie bardzo dużych argumentów np.1000 :)

0

Vogel napisał:
Gdzieś widziałem wzór na wersję silni dla liczb rzeczywistych (of koz standardowa definicja wtedy odpada).

Tylko, że wówczas nazywa się to funkcją gamma:
lim(przy n-&gtNieskończoność) (n!n^(x-1))/(x(x+1)(x+2)...*(x+n-1))

To oczywiście tylko jeden z możliwych opisów (są też inne równoważne, jednak mniej wygodne do napisania na forum :) )

a jeżeli chodzi o obliczanie silnii to najprostsze (ale niekoniecznie najlepsze) jest:

function Silnia(n: Byte): Int64; // można zmienić zakresy
begin
if n &lt 2 then
Silnia := 1
else
Silnia := n*Silnia(n-1);
end;--Jest jeszcze jeden błąd ... :)

Apel: Piszcie w tematach o jaki język programowania chodzi np. : [Delphi], [C++], itp.

0

Dla pascala to bym to zrobił tak:

program Tsilnia;
uses crt;
var silnia:real;
i,n:integer;
begin
clrscr;
silnia:=1;
Writeln('Podaj liczbę dla której policzyć silnię');
readln(n);
if n&lt0 then writeln('Za maa liczba');
if n=0 then writeln('Silnia=1');
if n&gt0 then begin
for i:=1 to n do
begin
silnia:=silnia*i;
end;
writeln('Silnia= ',silnia2);
end;
readln;
end.

Proste prawda

Jak by komus sie przydały to moge podesłać troche źródeł takich programików jest ich sporo na e równania i inne Zostały z czasów pierwszych kroków z programowaniem :-)

Pozdrowienia {hello}
Waldi Koronowo
[email protected]
Zdarza sie że pisze e przed i nie zwracajcie uwagi na to:D

0

Witam !
Mam problem ;)
W stosunku do poprzedniego programiku, roznica polega na koniecznosci zdefiniowania iteracyjnej wersji funkcji obliczajacej silnie i wyodrebnienie podprogramu (funkcji) realizujacej obliczenia.

Funkcja do obliczania silni ma:

  1. miec nazwe "silnia_iteracyjna"
  2. pobierac przez wartosc jeden parametr o nazwie "n",bedacy liczba typu LongInt
  3. zwracac w wyniku obliczona wartosc funkcji silnia, inaczej mowiac - n!
  4. funkcja ma obliczac wartosc silni w sposob iteracyjny

btw
0! = 1

--

pozdro_4_all

0

[wstyd] [wstyd] [wstyd]

--

pozdro_4_all

0

[niewinnosc] Dryobates ! Ty maniaku szybkości :-) Co się stało że wskazałeś na wolniejszy (ale piękny) rekurencyjny algorytm?

A tak na poważnie:
Jak ktoś słusznie zaznaczył, silnia jest w matematyce zdefiniowana rekurencyjnie, (z tym że ta osoba napisała że 0!=(o zgrozo)=0, a oczywiście 0!=1, sprawdźcie chociażby na kalkulatorkach). Z rekurencyjnej definicji wprost wynika rekurencyjny algorytm obliczania n!.

0!=1
n!=n*(n-1)!

Przekładając to na pseudo kod:

SILNIA_1(n)
0.Start

  1. Jeśli n=0 to Stop, wynik to 1
  2. Stop, wynik to n*SILNIA(n-1)

Piękne, niestety obliczeniowo mało praktyczne. Jak wiemy każda konstrukcja rekurencyjna ma swój iteracyjny odpowiednik, z tym że rekurencja jest wolniejsza (w przypadku silni różnica wynosi średnio 35%, ale już w przypadku wyznaczania n-tego wyrazu ciągu Fibonacciego ceną za przejrzysty, rekurencyjny kod jest około 50% spowolnienie).

SILNIA_2(n)
0. Start

  1. w=1
  2. i=1
  3. Wykonuj n razy
    3.1 n=n*i
    3.2 i=i+1
  4. Stop, wynik to w.

Oczywiscie jeżeli wpiszemy 100! dostrzeżemy dodatkowy problem - prawdopodobnie przekroczymy dopuszczalny zakres zminnej. (nawet na pewno jeśli użyliśmy jednego z typów atomowych). Dlatego dodatkowa gimnastyka z dynamicznym obsługiwaniem tablicy liczb może się okazać koniecznością (razem ze zdefiniowaniem arytmetyki tablicowej co okazuje się dosyć pracochłonne).

Jestem tylko warzywem, ale czy moglibyście się wytłumaczyć ze słów "wzór na wersję silni dla liczb rzeczywistych"? Silnia dla liczb rzeczywistych? hę? coś w stylu 4.23! Wy HERETYCY [diabel]
Już chyba prędzej przełknę że 0!=0 (przypominam 0!=1) niż wasze 3.24! albo 8.54! itd. Oczywiście silnia jest zdefiniowana w ciele liczb NATURALNYCH. (możecie się o tym ponownie przekonać na swoich kalkulatorkach, ale tym razem odwołuję się też do waszego zdrowego rozsądku, ile miało by wynosić 2.54! a ile np.2.55! ?)

Natomiast funkcjonują w matematyce dosyć ciekawe zależności, o których pokrótce opowiem:

  1. funkcja GAMMA. Wspomina o niej Dryobates :-) (i wie co robi)
    po pierwsze:

G(z+1)=z!

jesteśmy więc w domu. Tylko jaki jest wzór na G(z)? pozwolę sobie przytoczyć czytelniejszy zapis wynikający z definicji funkcji gamma (Dryobates odrobinę go uprościł arytmetycznie):

G(z)=lim n->infinite [ (n! * n^z) / (z * (z+1) * ... * (z+n) ]

Znany jest natomiast wzór na przybliżoną wartość funkcji gamma, z którego bezpośrednio wynika inna powszechnie stosowana zależność:

  1. wzór STIRLINGA: n!=Sqrt(2pin) * ( nn / en )
    gdzie Sqrt oznacza pierwiastek kwadratowy, a^b to a do potęgi b, e to stała Eulera (podstawa logarytmów naturalnych).

Jak łatwo dostrzec, wzór nie daje wartości rzeczywistej, tylko przybliżoną i jest przeznaczony dla stosunkowo dużych n (tzn. dla n=20 bład wynosi 0.5% a dla większych n nawet mniej). Oczywiście jest to bardzo szybka metoda, i jeżeli tylko możemy sobie pozwolić na pewne przybliżenia i błędy z jakimi się wiąże jej używanie, jest ona wskazana.

  1. nieskończony iloczyn: z!=PI k=1->infinite [ (1+1/k)^z / (1+z/k) ] Czasami się z tego korzysta przy upraszczaniu wyrażeń lub przy wyprowadzaniu dowodów.

Chciałem pokazać że istnieją co najmniej trzy odrębne sposoby podejścia do problemu:

  • rekurencja (najwolniej, najczytelniej)
  • iteracja (szybsza od rekurencji ale nadal zbyt wolna dla np. 10000!)
  • obliczenia przybliżone = wzór Stirlinga (szybkie, błąd pomijanie mały dla n>100)

Podobny schemat często się powtarza w różnych problemach, a wybór konkretnej metody jest uzależniony od wymagań jakie nakładamy na program.

Pozdrowienia [niewinnosc]

P.S. Jeśli macie mnie dość, dajcie znać.

0

P.S. Jeśli macie mnie dość, dajcie znać.

Ja nie mam dosc. Wrecz przeciwnie, ma prosbe: bywaj na forum i pisz jak najwiecej.

--
Pawel {Delphi 6 Personal}

Po pierwsze: naciśnij F1

0

Dzialanie programu glownego odpytujacego uzytkownika o kolejne liczby powinno byc analogiczne jak w przypadku poprzedniego zadania. Roznica sprowadza sie do sposobu obliczania wartosci funkcji silnia,
ktore to obliczenie ma byc realizowane przez wywolanie napisanej funkcji. Pozostale warunki (ograniczenia) - jak poprzednio (w szczegolnosci chodzi o sprawdzanie, czy mozna obliczyc wartosc
funkcji silnia dla podanego argumentu).

<font color="blue">PROGRAM <font color="darkblue"><font size="18">[size=]<font size="12">MA MIEC</span></span></span></span> MOZLIWOSC OBLICZENIA WARTOSCI FUNKCJI SILNIA DLA ARGUMENTU <font color="green">0 (0! = 1)</span>.</span>

btw
bylo to podane w minionym poscie [diabel]

Funkcja silnia jest zdefiniowana w postaci nastepujacej zaleznosci rekurencyjnej:

0! = 1
1! = 0!*1 = 1
2! = 1!*2 = 2
...

n! = (n-1)!*n (n>0)

Cala zaleznosc mozna tez zapisac jako (wersja iteracyjna):

[stop] [stop] n! = 1234 ... *(n-1)*n

--

pozdro_4_all

0

Dryobates ! Ty maniaku szybkości :-) Co się stało że wskazałeś na wolniejszy (ale piękny) rekurencyjny algorytm?

Napisałem, że najprostszy, ale nie najszybszy :)

  • obliczenia przybliżone = wzór Stirlinga (szybkie, błąd pomijanie mały dla n>100)

Tylko jak już wspomniałeś: przy n>100 pojawiają się problemy natury ściśle sprzętowej (ja miałem podobny problem przy obliczaniu liczby Pi - traciłem dokładność).

P.S. Jeśli macie mnie dość, dajcie znać.

Wręcz przeciwnie. W końcu ciekawe posty i ciekawe rozwiązania.
A tak na marginesie: skąd u ciebie taka wiedza matematyczna?

Jest jeszcze jeden błąd ... :)
--------Oficjalny kanał----------
Service for programmers w IRC:
Kanał: #4programmers.net
Serwer: warszawa.ircnet.pl
Sieć: POLNet
Port: 6667

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