Skocz do zawartości

Problem Z C++


Zygmunt

Rekomendowane odpowiedzi

/**********************************************************
*
*                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

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

#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

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

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 question.gif

pytanie 1: skąd przyszedł Ci do głowy pomysł użycia właśnie ld question.gif

 

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... dry.gif

Odnośnik do komentarza
Udostępnij na innych stronach

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 biggrin.gif

 

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 tongue.gif

 

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 wink.gif 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

po uruchomieniu program wypisze mi na ekran: 1,940000 + 0.060000 = 1 wink.gif 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

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 smile.gif

Odnośnik do komentarza
Udostępnij na innych stronach

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 smile.gif System priorytetów operatorów jest cechą danego języka i sprzęt nie ma tu nic do rzeczy smile.gif

 

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

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 wink.gif to architektura nie ma tu nic do rzeczy...

Odnośnik do komentarza
Udostępnij na innych stronach

Jesli kompilator nie jest jakis sfiksowany wink.gif 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

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ę
×
×
  • Dodaj nową pozycję...