Zygmunt Napisano Grudzień 24, 2005 Zgłoszenie Share Napisano Grudzień 24, 2005 /********************************************************** * * Program do obliczania silnii. * [email protected] * **********************************************************/ #include <iostream> using namespace std; double long silnia(int n) { double long wynik; if (n==0 || n==1) return 1; wynik = n * silnia (--n); return wynik; } int main() { int a; cout << "Podaj liczbe do obliczenia silnii z niej: "; cin >> a; cout << a << "! = " << silnia(a) << endl; } Oto cały problem: Zasada chyba jest prosta. Programik oblicza silnię, tylko dlaczego jeżeli w definicji funkcji silnii zmienie z double long na long wynik jest inny: tzn brakuje jednego czynnika (chyba dobrze określiłem). oto wyniki dla long: 0!= 1 1!= 1 2!= 1 3!= 2 4!= 6 ... itd. Natomiast przy sformuowaniu na double long dziala dobrze!!! Wydaje mi się to za duży błąd bo wkońcu to jest tylko definicja zmiennej i czegos brakuje. Może mi jednak ktos wytłumaczy co jest nie tak??? Bo ja szukałem i nie znalazłem odpowiedzi dlatego pisze. PS: Platforma nie ma nic do rzeczy.... I na win spod dev-cpp i pod anjuta to samo. Odnośnik do komentarza Udostępnij na innych stronach More sharing options...
Byku Napisano Grudzień 24, 2005 Zgłoszenie Share Napisano Grudzień 24, 2005 Hmm dziwne dla mnie jest to, ze dla long double wykonuje sie u ciebie dobrze (u mnie i w tym przypadku wychodza nieprawidlowe wyniki). Moim zdaniem winna jest linijka: wynik = n * silnia (--n); powinno byc: wynik = n * silnia (n-1); w 1 przypadku dla powiedzmy n=3 w oba miejsca wyrazenia wstawione zostanie n=2. I tu lezy przyczyna, dlaczego brakowało ci tego ostatniego czynnika. Odnośnik do komentarza Udostępnij na innych stronach More sharing options...
Zygmunt Napisano Grudzień 24, 2005 Autor Zgłoszenie Share Napisano Grudzień 24, 2005 no własnie nie Odnośnik do komentarza Udostępnij na innych stronach More sharing options...
Byku Napisano Grudzień 24, 2005 Zgłoszenie Share Napisano Grudzień 24, 2005 dziwne, ze u mnie jest wszystko w porządku po tej zmianie Z reszta pokombinuj sobie z tymi operatoriami (-- i ++) i sam obczaj jak to działa. A dziala tak, jak ci napisałem. Odnośnik do komentarza Udostępnij na innych stronach More sharing options...
Zygmunt Napisano Grudzień 24, 2005 Autor Zgłoszenie Share Napisano Grudzień 24, 2005 no to dlaczego po zmianie operatora z long na double long dziala OKi!!!!!! A inkrementacje i dekrementacje mam obczajona. Odnośnik do komentarza Udostępnij na innych stronach More sharing options...
Gość Zuk87 Napisano Grudzień 24, 2005 Zgłoszenie Share Napisano Grudzień 24, 2005 #include <cstdlib> #include <iostream> using namespace std; unsigned long silnia(unsigned long n) { unsigned long co=1; if (n!=1) {co=silnia(n-1)*n;} return co; } int main(int argc, char *argv[]) { for (unsigned long k=1;k<=5;k++) { cout << silnia(k) << "\n"; } system("PAUSE"); return EXIT_SUCCESS; } Może pomoże Ci to w czymś... Odnośnik do komentarza Udostępnij na innych stronach More sharing options...
Byku Napisano Grudzień 24, 2005 Zgłoszenie Share Napisano Grudzień 24, 2005 od razu proponuje i w powyzszym kodzie podmienic n-1 na --n. Apropo long'a to tak, jak mowie... Nie mam pojecia czemu u ciebie sie tak dzieje, bo u mnie tak samo bledne wyniki pokazuje. Odnośnik do komentarza Udostępnij na innych stronach More sharing options...
Zygmunt Napisano Grudzień 24, 2005 Autor Zgłoszenie Share Napisano Grudzień 24, 2005 OK takie male sprostowanie dla nieporozumienia --n daje to sampo co n=n-1 czty n-1 tyle ze zmienna n zostaje obnizona o 1 i od razu ta obnizona zmienna dobiera sie do funkcji czty tam petli i itp. n-- daje to sampo co n=n-1 czy n-1 tyle ze zmienna n zostaje obnizona o 1 i ale do funkcji czy tam petli jest brana nieobnizona zmienna n a dopiero po wykonaniu jest zmienna n obnizana. Natomiast mnie gnebi to, ze definiuje czy deklaruje zmienna czyli wynik powinno dawac ten sam a tymczasem tak nie jest!!! to tak jakbym chcial mnozyc w zbiorze liczb rzeczywistych i wynik nie pokrywalsie ze zbiorem liczb naturalnych.... Gdzie tymczasem zmienil sie tylko zakres i to samo jest z deklaracja czy tam definicja. Mam nadzieje ze udalo mi sie przekazac to o co mi chodzi PS: wiem byku ze tak samo pokazuje...... i to mnie wkurza Dobra poddaje sie co do in_ i de_krementacji, czyli mam rozumiec ze jezeli wpisze chocby przy wywolaniu funkcji predekrementacje to dotyczy sie calego n? czyli to rozumiem. I przyznaje blad ale deklaracja mnie dalej meczy..... Odnośnik do komentarza Udostępnij na innych stronach More sharing options...
Sanczo Napisano Grudzień 24, 2005 Zgłoszenie Share Napisano Grudzień 24, 2005 Sprawdziłem rzeczywiście jest dokładnie jak piszesz dla long double działa ok a dla long wszystko sie knoci... Nie wiem dlaczego tak sie dzieje, to jest co najmniej dziwne... pytanie 1: dlaczego używasz do silni long double pytanie 1: skąd przyszedł Ci do głowy pomysł użycia właśnie ld Sytuacje rozwiązuje tutaj zamiana linijki: wynik = n * silnia (--n); na wynik = n * silnia (n-1); Działa to dla long i long double. Myślę ,że w przypadku long kiedy --n wyrzucało bezsensowne wyniki następowało coś takiego: linijka wynik = n * silnia (--n); Prawa strona = : mnożymy n przez wynik funkcji silnia dekrementując n, w tym czasie pierwsze n prawdopodobnie również zmieniło wtedy swoją wartość na n-1. To tłumaczyło by działanie z typem long ale nie tłumaczy poprawności typu long double... Odnośnik do komentarza Udostępnij na innych stronach More sharing options...
Byku Napisano Grudzień 25, 2005 Zgłoszenie Share Napisano Grudzień 25, 2005 w tym czasie pierwsze n prawdopodobnie również zmieniło wtedy swoją wartość na n-1 Kod: wynik = n * silnia (--n); jest rownowazny: n = n-1; wynik = n * silnia (n); Tak wiec nie prawdopodobnie, a na pewno Dla mnie od poczatku dziwne nie bylo to, ze przy long double wyswietla bledne wyniki, ale ze przy long wyswietla poprawne (u was, bo u mnie nie). Jest to juz jedna z dwoch rzeczy, ktore bardzo chcialbym wiedziec Pierwsza to ta: Mam sobie kod: int main() { int x = 10,wynik; float y = 19.4,z = 0.06; wynik = y/x +z; printf("%f + %f = %d\n",y/x,z,wynik); return 0; } po uruchomieniu program wypisze mi na ekran: 1,940000 + 0.060000 = 1 why? Jesli zamienia 0.06 na 0.061 juz wynik daje 2. Ale czemu w pierwszym przypadku jest to jeden? Oo jesli zamienie float na double juz jest ok. Ale czy ktos mi potrafi racjonalnie wytlumaczyc, czemu w 1 przypadku tak sie dzieje? Odnośnik do komentarza Udostępnij na innych stronach More sharing options...
Gość _PaT Napisano Grudzień 25, 2005 Zgłoszenie Share Napisano Grudzień 25, 2005 po uruchomieniu program wypisze mi na ekran: 1,940000 + 0.060000 = 1 why? Jesli zamienia 0.06 na 0.061 juz wynik daje 2. Ale czemu w pierwszym przypadku jest to jeden? Oo jesli zamienie float na double juz jest ok. Ale czy ktos mi potrafi racjonalnie wytlumaczyc, czemu w 1 przypadku tak sie dzieje? To oczywiste. Nie wiem z jakiej książki uczysz się programować, ale najwyraźniej coś w niej pominęli... Minowicie ważny aspekt, którym jest sposób przechowywania przez komputer zmiennych. Zwykle temat nazywa się "precyzja liczb rzeczywistych/zmiennych". Naprawdę polecam poczytać o tym, bez tego moim zdaniem nie można zagłębić się w programowaniu z prostej przyczyny: programować powinno się tak, by przewidzieć, co program będzie czynił, nie natomiast na ślepo kompilować i oczekiwać rezultatów (tak niestety robi to znaczna większość uczących się). Odnośnik do komentarza Udostępnij na innych stronach More sharing options...
@perl Napisano Grudzień 26, 2005 Zgłoszenie Share Napisano Grudzień 26, 2005 oprocz BARDZO WAZNEGO problemu jaki poruszyl PaT istnieje tutaj jeszcze inny WAZNY problem na ktory warto zwrocic uwage, a mianowicie kolejnosc wykonywania operacji operatorowych zapis ktory zastosowales Zygmunt: wynik = n * silnia (--n); jest zly poniewaz nie wiadomo kiedy zostanie wykonana operacja dekrementacji na roznych kompilatorach (bo to od niego zalezy jak bedzie to wykonane) pojawia sie rozne wyniki, kompilator podejmuje decyzje o kolejnosci obliczen ze wzgledu na architekture sprzetu poprawny zapis wyrazenia powinien miec postac: --n; wynik = n * silnia (n); odsylam do lektury klasyki informatyki: "Język ANSI C" Brian W. Kernighan; Dennis M. Ritchie - mila lektura do poduszki ktora nauczy podstaw i standardow, potem latwo przejsc na programowanie obiektowe Odnośnik do komentarza Udostępnij na innych stronach More sharing options...
@Sorror Napisano Grudzień 26, 2005 Zgłoszenie Share Napisano Grudzień 26, 2005 zapis ktory zastosowales Zygmunt: wynik = n * silnia (--n); jest zly poniewaz nie wiadomo kiedy zostanie wykonana operacja dekrementacji na roznych kompilatorach (bo to od niego zalezy jak bedzie to wykonane) pojawia sie rozne wyniki, kompilator podejmuje decyzje o kolejnosci obliczen ze wzgledu na architekture sprzetu Ależ skąd System priorytetów operatorów jest cechą danego języka i sprzęt nie ma tu nic do rzeczy W Cepepe inkrementacje/dekrementacje mają jeden z najwyższych priorytetów, mianowicie piętnasty w 17-sto stopniowej skali. Odnośnik do komentarza Udostępnij na innych stronach More sharing options...
!Ci Napisano Grudzień 26, 2005 Zgłoszenie Share Napisano Grudzień 26, 2005 Ależ skąd smile.gif System priorytetów operatorów jest cechą danego języka i sprzęt nie ma tu nic do rzeczy smile.gif Zgadza sie... Jesli kompilator nie jest jakis sfiksowany to architektura nie ma tu nic do rzeczy... Odnośnik do komentarza Udostępnij na innych stronach More sharing options...
Gość _PaT Napisano Grudzień 26, 2005 Zgłoszenie Share Napisano Grudzień 26, 2005 Jesli kompilator nie jest jakis sfiksowany to architektura nie ma tu nic do rzeczy... Już pisałem, przeczytajcie sobie o precyzji przechowywania zmiennych w maszynach. Główny powód to ograniczanie wypływające z użycia ograniczonej ilości pamięci na daną zmienną, przy równoczesnym osiąganiu jak największej dokładności rzeczywistej. Architektura sprzętowa nie ma tu kompletnie nic do rzeczy, gdyż (o ile się nie mylę) rozmiary zmiennych w pamięci pomiędzy architekturami różnią się jedynie przy zmiennych całkowitych (integer), gdzie mamy nieograniczoną precyzję. Typy real, float, double zawsze otrzymują tyle samo pamięci (choć pewnie znajdą się jakieś wyjątki, ale na pewno nieliczne). Reasumując, jak chcesz się poważnie zabrać za programowanie to musisz sobie uświadomić różnorodność domyślnie alokowanej pamięci przez sprzęt. Ale to nie jest Twój problem Byku. Ty po prostu poczytaj sobie o tym, jak dane zmiennoprzecinkowe są przechowywane w pamięci komputera. Szczerze mówiąc nie orientuję się dokładnie w problemie, więc nie wahajcie się mnie poprawiać. Odnośnik do komentarza Udostępnij na innych stronach More sharing options...
Rekomendowane odpowiedzi
Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto
Jedynie zarejestrowani użytkownicy mogą komentować zawartość tej strony.
Zarejestruj nowe konto
Załóż nowe konto. To bardzo proste!
Zarejestruj sięZaloguj się
Posiadasz już konto? Zaloguj się poniżej.
Zaloguj się