[C++] Zmienne w bibliotece GMP dla C++

matemix
Użytkownik
Użytkownik
Posty: 465
Rejestracja: 10 cze 2008, o 19:38
Płeć: Mężczyzna
Lokalizacja: Wrocław
Podziękował: 12 razy
Pomógł: 1 raz

[C++] Zmienne w bibliotece GMP dla C++

Post autor: matemix »

Czy ktoś używa tu biblioteki GMP i wie jak deklarować następujące rodzaje zmiennych:
- zmienne będące liczbami całkowitymi z nieograniczoną liczbą cyfr,
- dowolnie duże liczby zmiennoprzecinkowe, z dokładnością do powiedzmy 10 miejsc po przecinku.

Szukam tego na stronie , ale nie znajduję. A zmiennych z przykładów, np. mpz_t kompilator w ogóle mi nie kompiluje i nie widzi jako deklarowania zmiennych. A może je się jakoś inaczej deklaruje niż proste

Kod: Zaznacz cały

int x
?

Jedyne zmienne jakie udało mi się zadeklarować to mpz_class, ale te są zdaje się krótsze niż zwykłe double mieszczące 15 cyfr.
Ostatnio zmieniony 3 kwie 2016, o 08:17 przez Afish, łącznie zmieniany 1 raz.
Powód: Poprawa wiadomości.
lukequaint
Użytkownik
Użytkownik
Posty: 219
Rejestracja: 5 maja 2010, o 18:27
Płeć: Mężczyzna
Lokalizacja: Wrocław
Podziękował: 1 raz
Pomógł: 75 razy

[C++] Zmienne w bibliotece GMP dla C++

Post autor: lukequaint »

Deklaruje się tak samo, ale następnie trzeba zainicjalizować odpowiednimi funkcjami (np. mpz_inits poniżej). Przeczytaj dokładnie dokumentację, wszystko jest jasno opisane. Cztery strony, na podstawie których stworzyłem przykład:
  • potrzebne nagłówki i polecenie do kompilacji (sprawdź, czy kompilujesz z flagami -lgmp i -lgmpxx; jeśli korzystasz z graficznego środowiska programistycznego, poszukaj w jego dokumentacji Compilation flags albo Linker flags, raczej to drugie):
  • przypisywanie wartości zmiennym typu całkowitego mpz_t:
  • dodawanie zmiennych: [url]https://gmplib.org/manual/Integer-Arithmetic.html#Integer-Arithmetic[/url]
  • wypisywanie zmiennych: [url]https://gmplib.org/manual/Formatted-Output-Strings.html#Formatted-Output-Strings[/url]
Przykład:

Kod: Zaznacz cały

// gmp_example.c
//
// kompilacja poleceniem
// gcc gmp_example.c -lgmp

#include "stdio.h"
#include "gmp.h"

int main()
{
    mpz_t bn1;
    mpz_t bn2;
    mpz_t bn3;

    // bn1 = 0
    mpz_inits(bn1, bn2, bn3, NULL);
    // bn2 = 1234567890987654321
    mpz_set_str(bn2, "1234567890987654321", 10);
    // bn3 = 11111
    mpz_set_si(bn3, 11111);
    // bn1 = bn1 + 8889
    mpz_add_ui(bn1, bn1, 8889);
    // bn3 = bn3 + bn1
    mpz_add(bn3, bn3, bn1);
    // bn2 = bn2 + bn3
    mpz_add(bn2, bn2, bn3);
    gmp_printf("%s = %Zd
", "bn1", bn1);
    gmp_printf("%s = %Zd
", "bn2", bn2);
    gmp_printf("%s = %Zd
", "bn3", bn3);
}
Spróbuj to skompilować. Program powinien wypisać:

Kod: Zaznacz cały

bn1 = 8889
bn2 = 1234567890987674321
bn3 = 20000
Liczbami zmiennoprzecinkowymi można posługiwać się w bardzo podobny sposób, powinieneś sobie poradzić. Odnośnik do dokumentacji: [url]https://gmplib.org/manual/Floating_002dpoint-Functions.html#Floating_002dpoint-Functions[/url]
matemix
Użytkownik
Użytkownik
Posty: 465
Rejestracja: 10 cze 2008, o 19:38
Płeć: Mężczyzna
Lokalizacja: Wrocław
Podziękował: 12 razy
Pomógł: 1 raz

[C++] Zmienne w bibliotece GMP dla C++

Post autor: matemix »

lukequaint pisze:Deklaruje się tak samo, ale następnie trzeba zainicjalizować odpowiednimi funkcjami (np. mpz_inits poniżej).
To tłumaczy dlaczego miałem z tym problem.
lukequaint pisze: Przeczytaj dokładnie dokumentację, wszystko jest jasno opisane.
Niestety jak na razie nie rozumiem większości tej dokumentacji.

Przykład programu działa i zwraca podane wyniki, ale mam kilka pytań.

Kod: Zaznacz cały

    mpz_inits(bn1, bn2, bn3, NULL);
Tutaj zmiennym są przypisane wartości zero i są inicjowane. Ale można je po prostu zainicjować bez przypisania im żadnej wartości?

Kod: Zaznacz cały

    mpz_set_str(bn2, "1234567890987654321", 10);
Ta funkcja "set" jak rozumiem po prostu przypisuje zmiennym wartości? A nie można tego zrobić np. tak bn2=11111? Co to jest ten ukośnik i 0 w drugiej wartości?

Kod: Zaznacz cały

    mpz_add_ui(bn1, bn1, 8889);
    mpz_add(bn3, bn3, bn1);
Tutaj mamy dodawanie - i mam rozumieć, że zapisu zwykłego dodawania program w przypadku tych zmiennych nie wykona?

Ogólnie mam do "przekonwertowania" na GMP następujący program, który nie ja napisałem, bo moje umiejętności przekracza i nie do końca potrafię zidentyfikować nawet rodzaje zmiennych, które zostały tu zastosowane (np. computeW):

Kod: Zaznacz cały

#include <iostream>
#include <iomanip>
using namespace std;
#include <conio.h>
#include <string>
#include <vector>
#include <cmath>
#include <limits>

//====================================================================================================================

double computeW( int pX, int pY, int pP, const vector < vector < int >>& pXn, const vector < int >& pXIndxs );
bool isNaturalNum( double value );

//====================================================================================================================

int main()
{
    int x;
    int y;
    int p;
    
    cout << "Podaj p: ";
    cin >> p;
    cout << "Podaj y: ";
    cin >> y;
    cout << "Podaj x: ";
    cin >> x;
    
    vector < vector < int >> xn( y - 1, vector < int >( x + 1 ) );
    
    for( auto & vec: xn )
    {
        for( int i = 0; i <= x; ++i )
        {
            vec[ i ] = i;
        }
    }
    
    vector < int > xIndxs( xn.size(), 0 );
    double w;
    bool exit = false;
    double counter = 0;
    unsigned long long howManyFound = 0;
    
    cout << "Start " << endl;
    
    while( !exit )
    {
        counter++;
        
        w = computeW( x, y, p, xn, xIndxs );
        if( isNaturalNum( w ) )
        {
            ++howManyFound;
            
            cout << "w = " << fixed << w << "; ";
            for( int i = 0; i < xn.size(); ++i )
            {
                cout << "x" << i + 1 << "=" << xn[ i ][ xIndxs[ i ] ] <<( i == xn.size() - 1 ? ""
                    : ", " );
            }
            cout << endl;
        }
        
        ++xIndxs[ 0 ];
        
        for( int j = xIndxs.size() - 1; j > 0; --j )
        {
            if( xIndxs[ j ] == x )
            {
                if( j == xIndxs.size() - 1 ) { exit = true; break; }
                
                ++xIndxs[ j + 1 ];
                
                for( int pom = j; pom >= 0; --pom )
                {
                    xIndxs[ pom ] = xIndxs[ j + 1 ];
                }
                
                break;
            }
        }
        
        if( xIndxs[ 0 ] == x + 1 )
        {
            if( xIndxs.size() >= 2 )
            {
                ++xIndxs[ 1 ];
                xIndxs[ 0 ] = xIndxs[ 1 ];
            }
            else
            {
                exit = true;
            }
        }
    }
    
    cout << "Koniec" << endl;
    cout << "wszystkich iteracji: " << fixed << setprecision( 0 ) << counter << endl;
    cout << "Policzonych całkowitych liczb w: " << howManyFound << endl;
    if(pow( 2, y+x )-pow( p, y )<0)
    {
    cout << "Ujemne" << endl;
	}	
    
    getch();
    return 0;
}
//====================================================================================================================
double computeW( int pX, int pY, int pP, const vector < vector < int >>& pXn, const vector < int >& pXIndxs )
{
    double retVal = 0;
    
    int lastPow;
    for( int i = 0; i < pXn.size(); ++i )
    {
        retVal += pow( 2, pXn[ i ][ pXIndxs[ i ] ] ) * pow( pP, i ) / pow( 2, i );
        
        lastPow = i + 1;
    }
    
    retVal += pow( pP, pY - 1 ) / pow( 2, pY - 1 );
    retVal *= pow( 2, pY - 1 );
    retVal /= abs(pow( 2, pX + pY ) - pow( pP, pY ));
    
    return retVal;
}

//*****************************************************************************
bool isNaturalNum( double value )
{
    unsigned long long intPart = value;
    double rest = value - intPart;
    
    return rest == 0;
}
//*****************************************************************************
Program zwraca błędne wartości dla większych wykładników i zmiennych, np. p=49667, y=5, x=73. Nie potrafi policzyć np.:

\(\displaystyle{ w=\left( 1, \frac {49667} {2}, \frac {49667^{2}} {4}, \frac{ 49667^{3}} {8}, \frac {49667^{4}} {16} \right) \cdot 16 \cdot \left[\begin{array}{ccc}2^{70}\\2^{70}\\2^{70}\\2^{70}\\1\end{array}\right]}\)

tylko zwraca błędny wynik, który identyfikuje także błędne jako całkowity. Zastanawiam, czy wystarczy, że przypiszę liczbie \(\displaystyle{ w}\) nieograniczoną długość i kilka miejsc po przecinku oraz zmienię retVal, żeby program przestał mieć problemy? Dodatkowo, czy jeżeli chcę sprawdzić naturalność \(\displaystyle{ w}\), a będzie ona ponad-standardowo duża, to też powinienem użyć jakiejś dedykowanej do tego funkcji? Ponadto czy coś takiego będzie działać w GMP:

Kod: Zaznacz cały

double computeW( int pX, int pY, int pP, const vector < vector < int >>& pXn, const vector < int >& pXIndxs )
Tu jest zdefiniowany chyba wektor lub działanie wektorowe. Jaką zmienną w GMP przypisać computeW?
lukequaint
Użytkownik
Użytkownik
Posty: 219
Rejestracja: 5 maja 2010, o 18:27
Płeć: Mężczyzna
Lokalizacja: Wrocław
Podziękował: 1 raz
Pomógł: 75 razy

[C++] Zmienne w bibliotece GMP dla C++

Post autor: lukequaint »

matemix pisze:

Kod: Zaznacz cały

    mpz_inits(bn1, bn2, bn3, NULL);
Tutaj zmiennym są przypisane wartości zero i są inicjowane. Ale można je po prostu zainicjować bez przypisania im żadnej wartości?
Zainicjowanie w tym przypadku to, jeśli dobrze rozumiem dokumentację, przypisanie im od razu jakiejś wartości (0 w tym przypadku). GMP musi w jakiś sposób skonfigurować wewnętrzne struktury. Z dokumentacji:
Before you can assign to a GMP variable, you need to initialize it by calling one of the special initialization functions. When you’re done with a variable, you need to clear it out, using one of the functions for that purpose.
matemix pisze:

Kod: Zaznacz cały

    mpz_set_str(bn2, "1234567890987654321", 10);
Ta funkcja "set" jak rozumiem po prostu przypisuje zmiennym wartości? A nie można tego zrobić np. tak bn2=11111? Co to jest ten ukośnik i 0 w drugiej wartości?

Kod: Zaznacz cały

    mpz_add_ui(bn1, bn1, 8889);
    mpz_add(bn3, bn3, bn1);
Tutaj mamy dodawanie - i mam rozumieć, że zapisu zwykłego dodawania program w przypadku tych zmiennych nie wykona?
W C++ można dzięki przeładowanym operatorom: . Kwestia doczytania, który operator odpowiada jakiej funkcji z poprzednio podanych przeze mnie stron dokumentacji.

Wybacz, ale nie mam czasu, by zająć się wklejonym przez Ciebie programem.
ODPOWIEDZ