Problemy początkującego programisty...

0

Witam wszystkich,

Od razu mówię, że jestem totalnym żółtodziobem, który rozpoczął przygodę z programowaniem w zeszłym tygodniu.

W ramach ćwiczeń napisałem sobie mały programik liczący ilość ziaren jaka znalazła by się na ostatnim polu szachownicy gdyby na każdym kolejnym znajdowała się liczba dwukrotnie większa niż na poprzednim (znana przypowieść o mędrcu i cesarzu).

Problem polega na tym, że program zlicza wartość jedynie do 30 pola czyli do wartości 1073741842, potem na polu 31 jest -2147483648 a następnie już same 0.

Proszę o podpowiedź jaką bibliotekę zastosować, zliczał powyżej tej liczby lub o krótkie wyjaśnienie zagadnienia.

Oto kod:

#include <iostream>
#include <conio.h>
#include <windows.h>

using namespace std;

int ziarenka=1, pole=0;

int main()
{
 cout <<"Program zliczajcy ziarenka ryzu:"<<endl;

 cout <<endl;

 while(pole<=63)
 {
    Sleep(500);
    pole++;
    ziarenka = ziarenka *2;
    cout <<"Numer pola: " <<pole <<", Ilosc ziarenek: "<<ziarenka <<"."<<endl;
 }

getch();
return 0;
}

Dziękuję z góry za pomoc i życzę miłego dnia,
AC

1

Swego czasu korzystałem z:

https://mattmccutchen.net/bigint/

Możesz zerknąć, powinno się nadać.

1

Ja bym skorzystał z long int, przydatny link:
https://www.tutorialspoint.com/cplusplus/cpp_data_types.htm

Tylko, że jak teraz się przyjrzałem to musisz szukać na polu 63, to albo musisz skorzystać z jakiejś biblioteki np. BIGNUM, albo zrobić strukturę do przechowywania takiej dużej liczby.

1

Problem związany jest z przekroczeniem maksymalnej wartości jaką może przyjąć int równą 2'147'483'647.
Możesz zamiast int użyć unsigned int, wtedy zakres będzie od 0 do 4'294'967'295.
Poczytaj sobie o podstawowych typach zmiennych.
Zamiast zmiennej int użyj np unsigned long long.

1
Madaoo napisał(a):

Ja bym skorzystał z long int, przydatny link:
https://www.tutorialspoint.com/cplusplus/cpp_data_types.htm

obawiam się, że może nie pomóc, w wielu kompilatorach long int to 4 bajty... Jeśli jest to raczej powinien skorzystać z typu uint64_t by miec pewność co do zakresu niezależnie od kompilatora! Ale chyba to też może być za mało

1

Dziękuję wszystkim za odpowiedzi.

Na tym etapie mojej wiedzy (czytaj: bliska 0) zastosowanie "unsigned long long" wystarczy do dalszej pracy.

Pozdrawiam,
AC

0

Ewentualnie w warunku pętli zmniejsz sobie ilość pól, tak, żeby nie przekroczyć w zmiennej ziarenka maksymalnej wartości.

1

uint64_t zdecydowanie wystarczy, na polu n jest 2n-1 ziaren.

Pole Ziaren
1 1 (20)
2 2 (21)
3 4 (22)
4 8 (23)
... ...
63 262
64 263
0

Witam,

Trochę cierpliwości i znalazłem jeszcze inną odpowiedź na swoje pytanie:

Należy uruchomić bibliotekę #<iomanip>
Następnie w kodzie zamiast int wpisujemy long double
Na samym końcu wprowadzamy funkcję setprecision(10000);

Docelowo powinno to wyglądać tak i działa bez zarzutu:

#include <iostream>
#include <conio.h>
#include <windows.h>
#include <iomanip>

using namespace std;

long double ziarenka=1, pole=0;

int main()
{
 cout <<"Program zliczajcy ziarenka ryzu:"<<endl;

 cout <<endl;
 cout <<setprecision(10000);

 while(pole<=63)
 {
    Sleep(250);
    pole++;
    ziarenka = ziarenka *2;
    cout <<"Numer pola: " <<pole <<", Ilosc ziarenek: "<<ziarenka <<"."<<endl;

 }

getch();
return 0;
}

Dziękuję raz jeszcze wszystkim za podpowiedzi!

Pozdrawiam,
AC

2

Uważaj z używaniem liczb zmiennoprzecinkowych. Akurat w przypadku pełnych potęg dwójki to nie jest problem, ale jeśli np. zmodyfikujesz zadanie i będziesz chciał 3x więcej na każdym polu niż na poprzednim, to nagle okaże się, że double nie jest dostatecznie precyzyjny (np. sprawdź, czy pow(2,63) == pow(2,63)-1 na Twojej architekturze)

0
#include <iostream>
#include <math.h>
#include <iomanip>

using namespace std;

int main()
{
    cout <<setprecision(100000);
    
    cout << "true\n" << pow(2,63) << " != \n" << (pow(2,63)-512) << endl;
    
    cout << "true\n" << pow(2,63) << " != \n" << (pow(2,63)-513) << endl;
    
    //Interesujące ;)
}

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