Liczenie silni

0

Witam zastanawiałem się jak liczyć silnie
niby no problem ale po jakmiś czasie się cyfry kończą w type int
nawet po powiększeniu go long'iem i tu moje pytanie jak zrobić zmienna która pozwalała by na operacje na tak dużych cyfrach interesuje mnie liczenie silnik co najmniej do 25

z góry dziękuje z odp

0

Pozostaje ci zmiana języka na jakiś który w standardzie ma baaardzo długie liczby, albo użycie jakiejś biblioteki do obliczeń na stringach (np. vlong)

0

spróbuj może unsigned long int

0

long long da rade chyba do 21! przechować a on chce większe ;)

0

chyba najprościej użyć GMP
http://gmplib.org/

0

Najprościej to chyba (jak sugerował Shalom) zmienić język. Np na Pythona.

# _*_ coding: utf-8 _*_
n=input("Dla jakiego n obliczyć silnię: ")

s=1
i=1
while i<=n:
   s*=i
   i+=1

print "%d! = %d" % (n,s)

Dla liczb czterocyfrowych (9999!) wynik jest na ekranie praktycznie natychmiast, dla większych (99999!) trzeba z minutę poczekać.

0

jeśli wydajność staje się ważna to polecam GMP np 99999! liczy ( samo liczenie nie piszę o wypisaniu na ekran) błyskawicznie (poniżej 0.1 s)

0

Chodzi mi oto że nauczyciel od matmy i infy stwirdził ze nie da sie powyżej 25 bo sie komputer załamie ja stwierdziłęm ze go poje... przeciez to dla komputera nie powinno problemów stanowić i chyba użyje GMP :) tlyko musze o tym poczytać na necie

0

Jeżeli to co napisałeś, to dokładne słowa nauczyciela (komputer się załamie) przy silni, to ja mam pytanie,
czyżby liceum w Rzeszowie?

0

Dokładnie to powiedział że wysiadzie i gimnazjum w Jarocinie tak tym Jarocinie ^^

0

Dobra zapakowałem biblioteke jaki teraz nagłówek użyć i jak zdeklarować zmienną ?

0
#include <iostream>
#include <fstream>
#include <gmpxx.h>

using namespace std;
int main()
{

    fstream plik;
    plik.open("silnia.txt",ios::out);

    mpz_class a;
    mpz_fac_ui (a.get_mpz_t(), 99999);

   // cout<<a;
    plik<<a;
    
    plik.close();
    return 0;
}

z linkerem -lgmpxx -lgmp działa pod MinGW (dev c++ code blocks)
bibliteki gmp (skompilowane!!) masz tutaj http://www.multiupload.com/2AGQMO0AI4

0

Dlaczego z użyciem pliku ? Ale THX zaraz przerobie i sie zobacyz jak to działa ^^

0

Kompilator: Default compiler
Building Makefile: "G:\projekt programming\silnia\Makefile.win"
Wykonywanie make...
make.exe -f "G:\projekt programming\silnia\Makefile.win" all
g++.exe -c main.cpp -o main.o -I"E:/Dev-Cpp/lib/gcc/mingw32/3.4.2/include" -I"E:/Dev-Cpp/include/c++/3.4.2/backward" -I"E:/Dev-Cpp/include/c++/3.4.2/mingw32" -I"E:/Dev-Cpp/include/c++/3.4.2" -I"E:/Dev-Cpp/include"

g++.exe main.o -o "Projekt1.exe" -L"E:/Dev-Cpp/lib"

main.o(.text+0x1e0):main.cpp: undefined reference to `__gmpz_fac_ui'

main.o(.text$_ZN10__gmp_exprIA1_12__mpz_structS1_ED1Ev[__gmp_expr<__mpz_struct [1], __mpz_struct [1]>::~__gmp_expr()]+0xd):main.cpp: undefined reference to __gmpz_clear' main.o(.text$_ZN10__gmp_exprIA1_12__mpz_structS1_EC1Ev[__gmp_expr<__mpz_struct [1], __mpz_struct [1]>::__gmp_expr()]+0xd):main.cpp: undefined reference to __gmpz_init'
main.o(.text$_ZlsIA1_12__mpz_structERSoS2_RK10__gmp_exprIT_S4_E[std::basic_ostream<char, std::char_traits<char> >& operator<< <__mpz_struct [1]>(std::basic_ostream<char, std::char_traits<char> >&, __gmp_expr<__mpz_struct [1], __mpz_struct [1]> const&)]+0x1c):main.cpp: undefined reference to `operator<<(std::ostream&, __mpz_struct const*)'
collect2: ld returned 1 exit status

make.exe: *** [Projekt1.exe] Error 1

Wykonanie zakończone

Taki błąd

0

jak od usuniesz komentarz przed cout a dasz przed plik<< to będzie na ekran ale nie mieści się w konsoli...

//EDIT

spróbuj tego
http://www.multiupload.com/EL8N1EBT6Y

0

@shadzio, 99999! ma 456569 cyfr i trudno to wyświetlić na konsoli.
@userek0, w Pythonie jednak prościej (chociaż dużo wolniej).

0

no wierzę nie upieram się tu w ogóle, bo bardziej złożone działania mogą być męką w GMP...

0

Dziękuje wszystkim program śmiga poprawie estetyke i gicior thx wielkie ^^

0

Nie trzeba zmieniać języka!

Wystarczy liczby wpisać do tablic. A nauczyciel tak się zna na tym co robi jak ja na balecie.

Właśnie pisze program, który robi coś podobnego. np. liczy 1872387678678653785 * 2323233. A i silnie z 1000 (1000!) nim policzysz. Na razie wyskakuje błąd, ale jak tylko go zniweluję, wstawię prawidłowy kod. Na razie masz to:

// program mnozacy dwie duze liczby i zwracajacy wartosc silni z pobranej liczby
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define SIZE 1000		//rozmiar tablic, wystarczajacy na potrzeby tworcy
short pobierz(short int [], int);		//pobiera liczbe w postaci tablicy cyfr i zwraca ilosc pobranych cyfr
void zeruj(short int [], int);		//zeruje kolejne elementy tablicy
void mnoz(short int [], short int [], short int [], int, short int, short int);		//mnozy dwie liczby w postaci tablicy cyfr
void liczsilnie(short int [], short int, int);	//liczy silnie wskazanej liczby, pobiera tablice, w ktorej zapisuje wynik i jej rozmiar

int main(void)
{
 	short int liczbap[SIZE], liczbad[SIZE], wynik[SIZE];	//liczbap- pierwsza liczba, liczbad- druga liczba
 	short int flaga, IloscZP, IloscZD;		//ZP- Znakow Pierwszej liczby, ZD- Znakow Drugiej liczby
 	short int n;	//zmienna pomocnicza
 	short int silnia; 	//liczba, ktorej silnia bedzie liczona
 	char wybor; 	//zmienna okreslajaca wybor dzialan uzytkownika
 	
 	printf("Jesli chcesz mnozyc liczby wpisz \"M\".\nJesli chcesz liczyc silnie wpisz \"S\".\nAby zakonczyc wpisz \"Z\"\n");
 	wybor = getchar();
	getchar();		
 	if (wybor == 'M' || wybor == 'm')	//liczenie iloczynu
 	{
 	   zeruj(liczbap, SIZE);
 	   zeruj(liczbad, SIZE);
 	   zeruj(wynik, SIZE);
 	   printf("Podaj pierwsza liczbe:\n");
 	   IloscZP = pobierz(liczbap, SIZE);
 	   printf("Podaj druga liczbe:\n");
 	   IloscZD = pobierz(liczbad, SIZE);	
 	   mnoz(liczbap, liczbad, wynik, SIZE, IloscZP, IloscZD);
 	   printf("Wynik to:\n");
 	   for (n = 0; n < SIZE; n++)	//petla wypisujaca wynik mnozenia dwoch liczb w postaci tablic cyfr
 	 	   printf("%1hd", *(wynik + n));
    }
    else if (wybor == 'S' || wybor == 's')		//liczenie silni
    {
	 	 printf("Podaj liczbe, ktorej silnie chcesz obliczyc\n");
	 	 scanf("%hd", &silnia);
	 	 liczsilnie(wynik, silnia, SIZE);
	 	 for (n = 0; n < SIZE; n++);
	 	 	 printf("%1hd", *(wynik + n));
	}
	else if (wybor == 'Z' || wybor == 'z')		//konczenie programu
		 return 0;
	else					//blad polecenia
		printf("nie ma takiego polecenia. Program zostanie zamkniety\n");
	putchar('\n');    
 	
 	system("PAUSE");
 	return 0;
}

void zeruj(short int tab[], int rozmiar)
{
 	 short int licznik;			//zmienna pomocnicza
 	 
 	 for (licznik = 0; licznik < rozmiar; licznik++)
 	 	 *(tab + licznik) = 0;
}
 	 	 
short pobierz(short int tab[], int rozmiar)
{
 	 short int flaga, n;			//zmienne pomocnicze
 	 short int robocza[rozmiar];		//tablica robocza, wykorzystana do pracy na tablicy glownej
 	 char znak;					//aktualnie pobierany, z wejscia, znak
 	 
 	 zeruj(robocza, rozmiar);
 	 for (n = 0; isdigit(znak = getchar()); n++)		//pobiera kolejne cyfry do tablic docelwej i roboczej
 	 	 *(robocza + n) = *(tab + n) = (short) znak - (short) '0';
 	 zeruj(tab, rozmiar);		//zeruje tablice glowna
 	 for (flaga = 0; flaga <= n; flaga++)		//zmienia kolejnosc wystepowania cyfr w tablicy glownej- 
 	 	 *(tab + (rozmiar - n + flaga)) = *(robocza + flaga);		//- ostatnia cyfra jest na ostatnim miejscu w tablicy
 	 	 
 	 return n;
}

void mnoz(short int pierwsza[], short int druga[], short int iloczyn[], int rozmiar, short IloscZP, short IloscZD)
{
 	 short int n, i, k, flaga, wynik, przepelnienie;
 	 short int robocza[rozmiar];
 	 
 	 zeruj(iloczyn, rozmiar);
 	 for (i = rozmiar - 1, k = 0; i  >= rozmiar - IloscZD; i--, k++)	//oblicza iloczyn
 	 {
 	  	 zeruj(robocza, rozmiar);
 	 	 for (n = rozmiar - 1, przepelnienie = 0; n >= 0; n--)		//mnozy i-ty element pierwszej tablicy przez -
 	 	 {															//n-ty element drugiej tablicy, wyniki zapisuje - 
	  	  	 wynik = *(pierwsza + i) * *(druga + n) + przepelnienie;		//w odpowiednich elementach tablicy roboczej
	  	 	 *(robocza + (n - k)) = wynik % 10;		//odejmowanie zmiennej k, odpowiada przesunieciu wyniku o k miejsc w lewo
	  	 	 przepelnienie = wynik / 10;
		 }
		 if (przepelnienie != 0)		//sprawdza czy nienastapilo przepelnienie
		 {
   		  	printf("Nastapil blad spowodowany zbyt duzym rozmiarem liczby. Program nie dziala prawidlowo\n");
   		  	break;
         }
		 for (n = rozmiar - 1, przepelnienie = 0; n >= 0; n--)  //sumuje odpowiednie elementy tablic roboczych do -
		 {															//odpowiadajacych im elementow tablicy iloczynu
		  	 *(iloczyn + n) = ( *(iloczyn + n) + *(robocza + n) + przepelnienie) % 10;
		  	 przepelnienie = ( *(iloczyn + n) + *(robocza + n) ) / 10;
		 }
		 if (przepelnienie != 0)  //sprawdza czy nienastapilo przepelnienie
		 {
   		  	printf("Nastapil blad spowodowany zbyt duzym rozmiarem liczby. Program nie dziala prawidlowo\n");
   		  	break;
         }
     }
}

void liczsilnie(short int wynik[], short int silnia, int rozmiar)
{	
 	 short int k, n,a, flaga; 		//zmienna pomocnicza
 	 short int ilosc; 		//ilosc cyfr pobranej liczby
 	 short int TabP[rozmiar], TabD[rozmiar];	//tablice pomocnicze

 	 zeruj(wynik, SIZE);
 	 zeruj(TabP, rozmiar);
 	 zeruj(TabD, rozmiar);
 	 for (ilosc = 1, k = 10; k <= silnia; ilosc++)		//liczy ilosc cyfr pobranej liczby
 	 	 k *= 10;
 	 for (a = silnia, n = rozmiar - 1;  n >= rozmiar - ilosc; n--)		//przypisuje pobrana liczbe tablicy
 	 {
 	  	 *(TabP + n) = a % 10;
 	 	 a /= 10;
     }
     silnia--;			//obniza wartosc liczby o 1 aby w nastepnej petli nie mnozyc dwoch tych samych liczb
 	 for (1 ; silnia > 0; silnia--)		//liczy silnie korzystajac z wczesniejszej petli
 	 {
	  	 zeruj(TabD, rozmiar);
	  	 for (k = silnia, n = rozmiar - 1; n > 0; n--)	//przypisuje aktualna liczbe tablicy
 	 	 {
	  	  	 *(TabD + n) = k % 10;
 	 	 	 k /= 10;
  		 }
  		 mnoz(TabP, TabD, wynik, rozmiar, ilosc + 1, ilosc + 1);	//mnozy aktualna liczbe przez wynik wczesniejszych iloczynow
  		 for (flaga = 0; flaga < rozmiar; flaga++)		// wynik aktualnego iloczynu
  		 	 *(TabP + flaga) = *(wynik + flaga);
  		 	   		 for (n = 0; n < SIZE; n++)	//petla wypisujaca wynik mnozenia dwoch liczb w postaci tablic cyfr
 	 	   printf("%1hd", *(wynik + n));
 	 	   putchar('\n');
     }
}
0

Zrobione:



// program mnozacy dwie duze liczby i zwracajacy wartosc silni z pobranej liczby
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define SIZE 3000		//rozmiar tablic, wystarczajacy na potrzeby tworcy
void pobierz(short int [], int);		//pobiera liczbe w postaci tablicy cyfr i zwraca ilosc pobranych cyfr
void zeruj(short int [], int);		//zeruje kolejne elementy tablicy
void mnoz(short int [], short int [], short int [], int);		//mnozy dwie liczby w postaci tablicy cyfr
void liczsilnie(short int [], short int, int);	//liczy silnie wskazanej liczby, pobiera tablice, w ktorej zapisuje wynik i jej rozmiar

int main(void)
{
 	short int liczbap[SIZE], liczbad[SIZE], wynik[SIZE];	//liczbap- pierwsza liczba, liczbad- druga liczba
 	short int n, flaga;	//zmienne pomocnicze
 	short int silnia; 	//liczba, ktorej silnia bedzie liczona
 	char wybor; 	//zmienna okreslajaca wybor dzialan uzytkownika
 	
 	printf("Jesli chcesz mnozyc liczby wpisz \"M\".\nJesli chcesz liczyc silnie wpisz \"S\".\nAby zakonczyc wpisz \"Z\"\n");
 	wybor = getchar();
	getchar();		
 	if (wybor == 'M' || wybor == 'm')	//liczenie iloczynu
 	{
 	   zeruj(liczbap, SIZE);
 	   zeruj(liczbad, SIZE);
 	   zeruj(wynik, SIZE);
 	   printf("Podaj pierwsza liczbe:\n");
 	   pobierz(liczbap, SIZE);
 	   printf("Podaj druga liczbe:\n");
 	   pobierz(liczbad, SIZE);	
 	   mnoz(liczbap, liczbad, wynik, SIZE);
 	   printf("Wynik to:\n");
 	   for (n = 0; n < SIZE; n++)	//petla wypisujaca wynik mnozenia dwoch liczb w postaci tablic cyfr
 	 	   printf("%1hd", *(wynik + n));
    }
    else if (wybor == 'S' || wybor == 's')		//liczenie silni
    {
	 	 printf("Podaj liczbe, ktorej silnie chcesz obliczyc\n");
	 	 scanf("%hd", &silnia);
	 	 zeruj(wynik, SIZE);
	 	 liczsilnie(wynik, silnia, SIZE);
	 	 for (n = 0; n < SIZE; n++)
	 	 	 printf("%1hd", *(wynik + n));
	}
	else if (wybor == 'Z' || wybor == 'z')		//konczenie programu
		 return 0;
	else					//blad polecenia
		printf("nie ma takiego polecenia. Program zostanie zamkniety\n");
	putchar('\n');    
 	
 	system("PAUSE");
 	return 0;
}

void zeruj(short int tab[], int rozmiar)
{
 	 short int licznik;			//zmienna pomocnicza
 	 
 	 for (licznik = 0; licznik < rozmiar; licznik++)
 	 	 *(tab + licznik) = 0;
}
 	 	 
void pobierz(short int tab[], int rozmiar)
{
 	 short int flaga, n;			//zmienne pomocnicze
 	 short int robocza[rozmiar];		//tablica robocza, wykorzystana do pracy na tablicy glownej
 	 char znak;					//aktualnie pobierany, z wejscia, znak
 	 
 	 zeruj(robocza, rozmiar);
 	 for (n = 0; isdigit(znak = getchar()); n++)		//pobiera kolejne cyfry do tablic docelwej i roboczej
 	 	 *(robocza + n) = (short) znak - (short) '0';
 	 zeruj(tab, rozmiar);		//zeruje tablice glowna
 	 for (flaga = 0; flaga < n; flaga++)		//zmienia kolejnosc wystepowania cyfr w tablicy glownej- 
 	 	 *(tab + (rozmiar - n + flaga)) = *(robocza + flaga);		//- ostatnia cyfra jest na ostatnim miejscu w tablicy
}

void mnoz(short int pierwsza[], short int druga[], short int iloczyn[], int rozmiar)
{
 	 short int n, i, k, wynik, przepelnienie;
 	 short int robocza[rozmiar], pomocnicza[rozmiar];
 	 
 	 zeruj(iloczyn, rozmiar);
 	 for (i = rozmiar - 1, k = 0; i >= 0; i--, k++)	//oblicza iloczyn
 	 {
 	  	 zeruj(robocza, rozmiar);
 	  	 zeruj(pomocnicza, rozmiar);
 	 	 for (n = rozmiar - 1, przepelnienie = 0; n >= 0; n--)		//mnozy i-ty element pierwszej tablicy przez -
 	 	 {															//n-ty element drugiej tablicy, wyniki zapisuje - 
	  	  	 wynik = *(pierwsza + i) * *(druga + n) + przepelnienie;		//w odpowiednich elementach tablicy roboczej
	  	 	 *(robocza + (n - k)) = wynik % 10;		//odejmowanie zmiennej k, odpowiada przesunieciu wyniku o k miejsc w lewo
	  	 	 przepelnienie = wynik / 10;
		 }
		 if (przepelnienie != 0)		//sprawdza czy nienastapilo przepelnienie
		 {
   		  	printf("Nastapil blad spowodowany zbyt duzym rozmiarem liczby. Program nie dziala prawidlowo\n");
   		  	break;
         }
		 for (n = rozmiar - 1, przepelnienie = 0; n >= 0; n--)  //sumuje odpowiednie elementy tablic roboczych do -
		 {															//odpowiadajacych im elementow tablicy iloczynu
			 *(pomocnicza + n) = *(iloczyn + n);
		  	 *(iloczyn + n) = ( *(iloczyn + n) + *(robocza + n) + przepelnienie) % 10;
		  	 przepelnienie = ( *(pomocnicza + n) + *(robocza + n) + przepelnienie) / 10;
		 }
		 if (przepelnienie != 0)  //sprawdza czy nienastapilo przepelnienie
		 {
   		  	printf("Nastapil blad spowodowany zbyt duzym rozmiarem liczby. Program nie dziala prawidlowo\n");
   		  	break;
         }
     }
}

void liczsilnie(short int wynik[], short int silnia, int rozmiar)
{	
 	 short int k, n,a, flaga; 		//zmienna pomocnicza
 	 short int ilosc; 		//ilosc cyfr pobranej liczby
 	 short int TabP[rozmiar], TabD[rozmiar];	//tablice pomocnicze
 	 
 	 for (ilosc = 1, k = 10; k <= silnia; ilosc++)		//liczy ilosc cyfr pobranej liczby
 	 	 k *= 10;
 	 for (k = silnia, n = rozmiar - 1; n >= 0; n--)		//przypisuje pobrana liczbe tablicy
 	 {
 	  	 *(TabP + n) = k % 10;
 	 	 k /= 10;
     }
     silnia--;			//obniza wartosc liczby o 1 aby w nastepnej petli nie mnozyc dwoch tych samych liczb
 	 for (1 ; silnia > 0; silnia--)		//liczy silnie korzystajac z wczesniejszej petli
 	 {
	  	 for (k = silnia, n = rozmiar - 1; n >= 0; n--)	//przypisuje aktualna liczbe tablicy
 	 	 {
	  	  	 *(TabD + n) = k % 10;
 	 	 	 k /= 10;
  		 }
  		 mnoz(TabP, TabD, wynik, rozmiar);	//mnozy aktualna liczbe przez wynik wczesniejszych iloczynow
  		 for (flaga = rozmiar - 1; flaga >= 0; flaga--)		// wynik aktualnego iloczynu
  		 	 *(TabP + flaga) = *(wynik + flaga);
     }
}



0

jak chcesz tylko do 25 to stablicuj wyniki

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