Biblioteki Biblioteka math.h complex.h - liczby zespolone liczby rzeczywiste float.h - liczny zmiennoprzecinkowe fenv.h - środowiski zmiennoprzecinkowe liczby całkowite limits.h - charakterystyka typów liczb calkowitych inittypes.h - konwersja liczb całkowitych stdckdiniot.h - kontrola arytmetyki liczb całkowitych atomic.h - typy atomowe stdbit.h - marzędzia bitowe i bajtowe stdbool.h - wartości i typy logiczne tgmath.h - funkcje matematyczne niezależne od typu

Liczby Liczby 0–F16 w systemiedziesiętnym, ósemkowym i dwójkowym   0hex   =   0dec   =   0oct     0     0     0     0   1hex = 1dec = 1oct 0 0 0 1 2hex = 2dec = 2oct 0 0 1 0 3hex = 3dec = 3oct 0 0 1 1 4hex = 4dec = 4oct 0 1 0 0 5hex = 5dec = 5oct 0 1 0 1 6hex = 6dec = 6oct 0 1 1 0 7hex = 7dec = 7oct 0 1 1 1 8hex = 8dec = 10oct 1 0 0 0 9hex = 9dec = 11oct 1 0 0 1 Ahex = 10dec = 12oct 1 0 1 0 Bhex = 11dec = 13oct 1 0 1 1 Chex = 12dec = 14oct 1 1 0 0 Dhex = 13dec = 15oct 1 1 0 1 Ehex = 14dec = 16oct 1 1 1 0 Fhex = 15dec = 17oct 1 1 1 1 Rodzaje liczb całkowite int char wymierne z pomocą typu mpq_t z biblioteki GMP ( GNU Multiple Precision Arithmetic Library ) z użyciem struktur The Rational Number Class in C by Peter BurdenRational Arithmetic by R. Sedgewick zmiennoprzecinkowe float double wartości specjalne zespolone kwaterniony

Dodatkowo rodzaj liczby definiują : specyfikatory podstawa systemu liczbowego binarne ósemkowe (oktalne) dziesiętne szesnastkowe

Jak widać nie ma : Liczb niewymiernych ( chyba że korzystamy z obliczeń symbolicznych, np. program Maxima CAS )

liczby binarne

Sposoby : itoa snprintf Where is the itoa function in Linux? Binarna stała całkowita z użyciem rozszerzenia gcc za pomoc operacji na bitach, np. shift Binarna stała całkowita z użyciem rozszerzenia gcc gcc - Binary-constants prefix ‘0b’ lub ‘0B’ sekwencja cyfr ‘0’ lub ‘1’ suffix ‘L’ lub ‘UL’

Następujące zapisy są identyczne: i = 42; // decimal i = 0x2a; // hexadecimal i = 052; // octal i = 0b101010; // binary

int i = 1 << 9; /* binary 1 followed by 9 binary 0's */ Code Replay : C represent int in base 2

Liczby szestnastkowe ( hexadecymalne)

Liczba szesnastkowa: jest poprzedzana przez przedrostek „0x” lub „0X” jest wartością całkowitą i można ją przechowywać w typie całkowitym typów danych (char, short lub int)

Przykłady: „0x64” odpowiada 100 w systemie dziesiętnym wartość szesnastkowa 3E8 jest reprezentowana w c jako 0x3E8

Każdy bajt ( 8 bitów) to 2-cyfrowa liczba szesnastkowa

Maksymalna liczba całkowita bez znaku zajmująca n bajtów: 1 bajt = 8 bitów: 2 bajty = 16 bitów 4 bajty = 32 bity 8 bajtów = 64 bity

Prezentacja liczb rzeczywistych w pamięci komputera How Computers Use Numbers Floating Point Math by Erik Wiffin float exposed by Bartosz Ciechanowski The Theory Behind How Computers Subtract by Rutvik Liczby rzeczywisty

W wielu książkach nie ma w ogóle tego tematu. Być może ten temat może wydać Ci się niepotrzebnym, lecz dzięki niemu zrozumiesz, jak komputer radzi sobie z przecinkiem what-every-computer-programmer-should by Josh Habermanoraz dlaczego niektóre obliczenia dają niezbyt dokładne wyniki.Metody numeryczne - autorzy : Piotr Krzyżanowski i Leszek Plaskota — Uniwersytet Warszawski, Wydział Matematyki, Informatyki i Mechaniki Na początek trochę teorii. Do przechowywania liczb rzeczywistych przeznaczone są 3 typy: float, double oraz long double. Zajmują one odpowiednio 32, 64 oraz 80 bitów. Wiemy też, że komputer nie ma fizycznej możliwości zapisania przecinka. Spróbujmy teraz zapisać jakąś liczbę wymierną w formie liczb binarnych. Nasza liczba to powiedzmy 4.25. Spróbujmy ją rozbić na sumę potęg dwójki: 4 = 1*22 + 0*21+0*20. Dobra - rozpisaliśmy liczbę 4, ale co z częścią dziesiętną? Skorzystajmy z zasad matematyki - 0.25 = 2-2. Zatem nasza liczba powinna wyglądać tak: 100.01 Ponieważ komputer nie jest w stanie przechować pozycji przecinka, ktoś wpadł na prosty ale sprytny pomysł ustawienia przecinka jak najbliżej początku liczby i tylko mnożenia jej przez odpowiednią potęgę dwójki. Taki sposób przechowywania liczb nazywamy zmiennoprzecinkowym, a proces przekształcania naszej liczby z postaci czytelnej przez człowieka na format zmiennoprzecinkowy nazywamy normalizacją. Wróćmy do naszej liczby - 4.25. W postaci binarnej wygląda ona tak: 100.01, natomiast po normalizacji będzie wyglądała tak: 1.0001*22. W ten sposób w pamięci komputera znajdą się dwie informacje: liczba zakodowana w pamięci z "wirtualnym" przecinkiem oraz numer potęgi dwójki. Te dwie informacje wystarczają do przechowania wartości liczby. Jednak pojawia się inny problem - co się stanie, jeśli np. będziemy chcieli przełożyć liczbę typu ? Otóż tutaj wychodzą na wierzch pewne niedociągnięcia komputera w dziedzinie samej matematyki. 1/3 daje w rozwinięciu dziesiętnym 0.(3). Jak zatem zapisać taką liczbę? Otóż nie możemy przechować całego jej rozwinięcia (wynika to z ograniczeń typu danych - ma on niestety skończoną liczbę bitów). Dlatego przechowuje się tylko pewne przybliżenie liczby. Jest ono tym bardziej dokładne im dany typ ma więcej bitów. Zatem do obliczeń wymagających dokładnych danych powinniśmy użyć typu double lub long double. Na szczęście w większości przeciętnych programów tego typu problemy zwykle nie występują. A ponieważ początkujący programista nie odpowiada za tworzenie programów sterujących np. lotem statku kosmicznego, więc drobne przekłamania na odległych miejscach po przecinku nie stanowią większego problemu.

Program wyświetlający wewnętrzną reprezentację liczby podwójnej precyzji:How to get memory representation-doubleIEEE-754 Floating Point Converter #include

int main(void) { double a = 1.0 / 3; size_t i; size_t iMax= sizeof a;

printf("bytes are numbered from 0 to %x\n", (unsigned)iMax -1);

for (i = 0; i 0 ; --i)

printf("%x", ((unsigned char *)&a)[i-1]);

printf(" \n"); return 0; }

Daje wynik:

bytes are numbered from 0 to 7 byte number 0 = 55 byte number 1 = 55 byte number 2 = 55 byte number 3 = 55 byte number 4 = 55 byte number 5 = 55 byte number 6 = d5 byte number 7 = 3f

hex memory representation of 0.333333 is : 3fd5555555555555

0 01111111101 01010101010101010101010101010101010101010101010101012 = 3FD5 5555 5555 555516 ≙ +2−2 × (1 + 2−2 + 2−4 + ... + 2−52) ≈ 1/3

Given the hexadecimal representation 3FD5 5555 5555 555516, Sign = 0 Exponent = 3FD16 = 1021 Exponent Bias = 1023 (constant value; see above) Fraction = 5 5555 5555 555516 Value = 2(Exponent − Exponent Bias) × 1.Fraction – Note that Fraction must not be converted to decimal here = 2−2 × (15 5555 5555 555516 × 2−52) = 2−54 × 15 5555 5555 555516 = 0.333333333333333314829616256247390992939472198486328125 ≈ 1/3

Zobacz również: dumpfpdumpfp: A Tool to Inspect Floating-Point Numbers by Joshua Haberman

Liczby całkowiteLiczba całkowitej bez znaku (ang. unsigned char lub uint8_t ) zajmującej 1 bajt, czyli 8 bitów.

Ta tabela ilustruje wartość

Oznaczenia MSB = najbardziej znaczący bit LSB = najmniej znaczący bit

Bit position i 7 6 5 4 3 2 1 0 Binary digit 1 0 0 1 0 1 0 1 Bit weight = ( 2i ) 27 26 25 24 23 22 21 20 Bit position label MSB LSBLiczba całkowita bez znaku zajmująca 2 bajty = 16 bitów ( uint16_t )Wartość dziesiętna (decymalna) = 769 dwójkowa (binarna) = 1100000001 hexadecymalna = 0x0301

+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

Zadania: konwersja dwóch wartości 8-bitowych na jedną wartość 16-bitową w Csubethasoftware : converting-two-8-bit-values-to-one-16-bit-value-in-c dzielenie całkowitej liczby 16 bitowej bez znaku na 2 bajtysubethasoftware: splitting-a-16-bit-value-to-two-8-bit-values-in-c

Konwersje liczb

/*

gcc b.c -Wall -Wextra

*/

#include #include

/* https://stackoverflow.com/questions/5488377/converting-an-integer-to-binary-in-c

If you want to transform a number into another number (not number to string of characters), and you can do with a small range (0 to 1023 for implementations with 32-bit integers), you don't need to add char* to the solution. pmg

*/ unsigned unsigned_int_to_bin(unsigned int k) { if (k == 0) return 0; if (k == 1) return 1; /* optional */ return (k % 2) + 10 * unsigned_int_to_bin(k / 2); }

int main(void){

unsigned int u = 1019; if (u>1023) {fprintf(stderr, "input number decimal u = %d is too big; close the program ! \n", u); return 1;}

unsigned int b = unsigned_int_to_bin(u); fprintf(stdout, "decimal u = %d as a binary unsigned number = %d\n", u, b);

return 0;

Wynik:

gcc b.c -Wall -Wextra ./a.out decimal u = 1019 as a binary unsigned number = 1111111011

Konwersja zapisu matematycznego na program komputerowy w języku C sumowanie

W zapisie matematycznym do przedstawiania w zwarty sposób sumowania wielu podobnych wyrazów ( serii) stosuje się symbol sumowania , wywodzący się z wielkiej greckiej litery sigma. Jest on zdefiniowany jako:

gdzie oznacza indeks sumowania to zmienna przedstawiająca każdy kolejny wyraz w szeregu to dolna granica sumowania to górna granica sumowania. Wyrażenie „i = m” pod symbolem sumowania oznacza, że indeks rozpoczyna się od wartości Następnie dla każdego kolejnego wyrazu indeks jest zwiększany o 1, aż osiągnie wartość (tj. ), który jest ostatnim wyrazem sumowania.

#include

int summation(const int m, const int n ) { int s = 0; for(int i=m; i<=n; ++i)

s += i;

return s; }

int main() { int sum; int m = 1; // lower index int n = 100; // upper index

sum = summation(m,n);

printf("sum of integer numbers from %d to %d is %d\n", m, n, sum); return 0;

gcc s.c -Wall -Wextra ./a.out sum of integer numbers from 1 to 100 is 5050Suma sum:

Sumy są obliczane od prawej do lewej. Oznacza to, że sigma po lewej stronie jest najwyżej zagnieżdżoną pętlą: Math to Code by cameron smith

sum = 0; for (i =1; i<=4; i++) for (j=1; j

int product(const int m, const int n ) { int p = 1; for(int i=m; i<=n; ++i)

p *= i;

return p; }

int main() { int p; int m = 1; // lower index int n = 10; // upper index

p = product(m,n);

printf("product of integer numbers from %d to %d is %d\n", m, n, p);

Dla zakresu [1,10] program działa poprawnie gcc p.c -Wall -Wextra ./a.out product of integer numbers from 1 to 10 is 3628800

Dla zakresu [1,100] program daje dziwny wynik: gcc p.c -Wall -Wextra ./a.out product of integer numbers from 1 to 100 is 0

Wartość iloczynu możemy obliczyć za pomoca wolfram alfa. Product[k, {k, 1, 100}] = 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000

Liczba ma 159 cyfr, to więcej niż zakres dostępnych standardowych liczb całkowitych. Przekroczenie zakresu powoduje błędny wynik.

Jeśli dolny zakres wynosi 1 to wynik jest równy silni ( ang factorial). Wartość silnii rośnie szybciej niż wzrost funkcji wykładniczej.

Sprawdzenie czy nie będzie przekroczenia zakresu liczb powinniśmy wykonać przed wykonaniem działania: #include #include // INT_MAX /* http://c-faq.com/misc/sd26.html functions for ``careful'' multiplication.

*/

int chkmul(int a, int b) { int sign = 1; if(a == 0 || b == 0) return 0; if(a 0) ? INT_MAX : INT_MIN;

return sign*a*b; }

int product(const int m, const int n ) { int p = 1; for(int i=m; i<=n; ++i)

fprintf(stdout,"i = %d \t", i); p = chkmul(p,i); fprintf(stdout,"p = %d \n", p);

return p; }

int main() { int p; int m = 1; // lower index int n = 100; // upper index

p = product(m,n);

printf("product of integer numbers from %d to %d is %d\n", m, n, p);

gcc p.c -Wall -Wextra ./a.out i = 1 p = 1 i = 2 p = 2 i = 3 p = 6 i = 4 p = 24 i = 5 p = 120 i = 6 p = 720 i = 7 p = 5040 i = 8 p = 40320 i = 9 p = 362880 i = 10 p = 3628800 i = 11 p = 39916800 i = 12 p = 479001600 i = 13 int overflow p = 2147483647