Racionální čísla
Racionální čísla jsou zlomky ve tvaru a / b. Pro uložení racionálních čísel v libgmp slouží datový typ mpq_t
. Všechny funkce v libgmp pro práci s racionálními čísly předpokládají, že jim na vstup předáte čísla v tzv. kanonickém tvaru, a také v kanonickém tvaru vracejí výsledek. Kanonický tvar znamená, že čitatel a a jmenovatel b mají gcd(a, b) = 1 a že jmenovatel je kladný. Nula má unikátní reprezentaci 0/1. Přiřazení zlomku do proměnné nekanonizuje výsledek. Je na uživateli, aby v takovém případě kanonizoval výsledek pomocí funkce mpq_canonicalize
.
Inicializace a dealokaci proměnné provedeme pomocí funkcí mpq_init
a mpq_clear
. K nastavení hodnoty pak můžeme použít funkci mpq_set_ui
, případně mpq_set_str
. Příklad:
mpq_t num1, num2; mpq_init(num1); mpq_init(num2); mpq_set_ui(num1, 37107UL, 1254UL); mpq_set_str(num2, "41/152", 10); mpq_canonicalize(num1); mpq_canonicalize(num2); gmp_printf("num1 = %Qi\n", num1); /* vypíše num1 = 651/22 */ gmp_printf("num2 = %Qi\n", num2); /* vypíše num2 = 41/152 */ mpq_clear(num1); mpq_clear(num2);
Aritmetické operace
Racionální čísla můžeme samozřejmě sčítat, odčítat, násobit, dělit, apod. Ke sčítání slouží funkce mpq_add
.
mpq_t num1, num2, r; mpq_inits(num1, num2, r, NULL); mpq_set_ui(num1, 651UL, 22UL); mpq_set_str(num2, "41/152", 10); mpq_add(r, num1, num2); gmp_printf("num1 = %Qi\n", num1); /* vypíše num1 = 651/22 */ gmp_printf("num2 = %Qi\n", num2); /* vypíše num2 = 41/152 */ gmp_printf("r = %Qi\n", r); /* vypíše r = 49927/1672 */ mpq_clears(num1, num2, r, NULL);
V příkladu vidíme, že místo vícenásobného volání mpq_init
a mpq_clear
můžeme použít jedno volání mpq_inits
a mpq_clears
. Můžeme si také všimnout, že pokud přiřadíme do mpq_t
již čísla v kanonickém tvaru, nemusíme volat mpq_canonicalize
. Mezi další aritmetické funkce patří mpq_sub
, mpq_mul
a mpq_div
. Reciprokou hodnotu můžeme vypočíst pomocí mpq_inv
.
Operace s čitatelem a jmenovatelem
K přímému přístupu k čitateli a jmenovateli slouží makra mpq_numref
a mpq_denref
, které vracejí ukazatel na strukturu uvnitř mpz_t
, který může být předán a modifikován funkcemi, které jsme probírali v předchozích dvou dílech seriálu. Uvedu příklad.
mpq_t number; mpq_init(number); mpq_set_str(number, "651/22", 10); gmp_printf("number = %Qi\n", number); /* vypíše number = 651/22 */ mpz_add(mpq_numref(number), mpq_numref(number), mpq_denref(number)); gmp_printf("number = %Qi\n", number); /* vypíše number = 673/22 */ mpq_clear(number);
Čísla s plovoucí desetinnou čárkou
Čísla s plovoucí desetinnou čárkou jsou uložena v datovém typu mpf_t
. Každé takové číslo může mít svou vlastní minimální přesnost (velikost mantisy v bitech). Přesnost, která bude použita pro nové proměnné, se nastavuje globálně pomocí funkce mpf_set_default_prec
. Aby si proměnná nastavila tuhle globální minimální přesnost, musíme ji inicializovat pomocí mpf_init
. Pak je tu ale ještě k dispozici funkce mpf_init2
, která jako druhý argument bere minimální přesnost a nehledí tak na tu nastavenou globálně.
mpf_t x, y; mpf_init(x); /* použít globálně nastavenou minimální přesnost */ mpf_init2(y, 256); /* použít minimální přesnost 256 bitů */ /* ... */ mpf_clear(x); mpf_clear(y);
Nastavit hodnotu do proměnné mpf_t
můžeme pomocí mpf_set_d
, která jako druhý argument bere double
. Dále máme k dispozici mpf_set_str
, která bere argument v podobě textového řetězce.
mpf_t num1, num2; mpf_inits(num1, num2, NULL); mpf_set_d(num1, 3.141592653589793); mpf_set_str(num2, "1.4e-10", 10); gmp_printf("num1 = %.20Ff\n", num1); gmp_printf("num1 = %.20Ff\n", num2); mpf_clears(num1, num2, NULL);
Případně můžeme použít kombinovanou inicializaci a přiřazení pomocí funkcí mpf_init_set_d
a mpf_init_set_str
.
Aritmetické operace
Čísla s plovoucí desetinnou čárkou můžeme samozřejmě sčítat, odčítat, násobit a dělit. K tomu slouží funkce mpf_add
, mpf_sub
, mpf_mul
a mpf_div
. Pro výpočet odmocniny máme k dispozici funkci mpf_sqrt
.
mpf_t r, number; mpf_init(r); mpf_init_set_str(number, "115", 10); mpf_sqrt(r, number); gmp_printf("r = %.20Ff\n", r); /* vypíše r = 10.72380529476360830480 */ mpf_clears(r, number, NULL);
Bohužel funkce jako sinus, cosinus nebo logaritmus nejsou v libgmp implementované.