sâmbătă, 29 iunie 2013

Web Hosting gratuit cu Google Drive

Cu Google Drive puteţi hosta resurse web HTML, CSS, şi Javascript. Drive nu oferă suport pentru scripturile server-side scrise, de exemplu, în PHP.
Practic vă puteţi hosta websiteul pe Google Drive.

Iată cum puteţi face asta:

  1. Deschideţi Drive (trebuie să aveţi cont Google), creaţi un nou folder şi partajaţi-l (Share) ca Public on the web.
    Click dreapta pe folder, selectaţi Share, o nouă fereastră va apărea, click pe Change... şi faceţi-l Public.
  2. Uploadaţi-vă fişierele în acest folder.
  3. Click dreapta pe un fişier din acest folder şi algeţi Details. O nouă fereastră va apărea în dreapta.
  4. Scroll down până găsiţi Hosting. Acela este URL-ul către fişierul hostat.
Iată un exemplu cu un fişier hostat pe Drive: hangme.js.

miercuri, 19 iunie 2013

Bacalaureat 2013 - Problema 4 - Subiectul 3 (Sesiunea speciala)

Fişierul bac.txt conţ ine un şir de cel pu ţin trei şi cel mult 1000000 de numere naturale cu cel mult nouă cifre. Numerele din şir sunt separate prin câte un spa ţiu.
Se cere să se afişeze pe ecran, separate printr-un spa ţiu, două numere distincte, anume cel mai mic număr par cu două cifre şi cel mai mare număr par cu două cifre care NU fac parte din şir.
Dacă nu există două astfel de valori, pe ecran se afisează mesajul Nu exista.
Pentru determinarea numerelor cerute se utilizează un algoritm eficient din punctul de vedere al timpului de executare.
Exemplu: dacă fişierul bac.txt con ţine valorile
7 2 40 5 10 15 11 12 18 350
se afişează pe ecran numerele 14 98.

Arată Soluţia

Complexitatea algoritmului este `O(n)` (liniar).

Bacalaureat 2013 - Problema 3 - Subiectul 3 (Sesiunea speciala)

Se consideră subprogramul sub, cu trei parametri:
  • n, prin care primeşte un număr natural (2<n<50);
  • v, prin care primeşte un tablou unidimensional cu n elemente, numere naturale cu cel mult 4 cifre;
  • x, prin care primeşte un număr natural cu cel mult 4 cifre. Cel pu ţin unul dintre elementele tabloului are valoarea x.
Subprogramul modifică ordinea valorilor din tablou, astfel încât toate valorile egale cu x să ocupe primele poziţ ii din v, iar celelalte valori să se regăsească în continuarea acestora.
Tabloul modificat este furnizat tot prin parametrul v.
Scrie ţi defini ţia completă a subprogramului.
Exemplu: dacă n=9, v=(2, 1, 0, 1, 7, 0, 1, 4, 5) şi x=1, atunci, după apel, o soluţ ie posibilă este v=(1, 1, 1, 2, 0, 7, 0, 4, 5).

Arată Soluţia

Bacalaureat 2013 - Problema 5 - Subiectul 2 (Sesiunea speciala)

Se consideră un text cu cel mult 100 de caractere (litere mici ale alfabetului englez şi spaţ ii), în care cuvintele sunt separate prin câte un spaţ iu. Înaintea primului cuvânt şi după ultimul cuvânt nu există spa ţii.
Scrieţ i un program C/C++ care citeşte de la tastatură un text de tipul men ţionat mai sus şi determină transformarea acestuia în memorie prin înlocuirea fiecărui cuvânt format din trei litere cu simbolul *. Programul afişează pe ecran textul ob ţinut.
Exemplu: pentru textul

bun este izvorul ce are apa rece

se afişează

* este izvorul ce * * rece

Algoritmul reţine adresa de început a fiecărui cuvânt şi numără numărul de litere din fiecare cuvânt până când întâlneşte un caracter spaţiu.
Aici se verifică dacă a fost întâlnit un cuvânt de 3 litere, caz în care se deplasează tot şirul spre stânga, iar pe prima poziţie din cuvânt se inserează caracterul *.
Indiferent dacă a fost găsit un cuvânt de 3 litere, după fiecare spaţiu începe un nou cuvânt ceea ce înseamnă că start este actualizat, iar cnt este resetat.

Arată Soluţia

luni, 17 iunie 2013

Mărimi fizice - Sistemul Internaţional

Mărimea fizică este o proprietate fizică măsurabilă.
Ea caracterizează starea unui sistem fizic. Are forma:

marime fizică = valoare numerică x unitatea de măsură

A măsura o mărime fizică înseamnă a o compara cu o altă mărime fizică pe care o numim unitate de măsură.
Acestei unităţi standard îi este atribuit un nume unic şi valoarea 1.0, reprezentând 1 unitate din respectiva mărime fizică.
Exemplu de mărimi fizice: lungimea, masa, viteza, forţa, timpul, etc.

Prin convenţie internaţională (1971, a 14-a Conferință Generală de Măsuri și Greutăți) au fost stabilite 7 mărimi fizice fundamentale care formează baza Sistemul Internaţional de Unităţi, prescurtat SI.
Celelalte unităţi (mărimi) sunt derivate din acestea, adică definite în termeni de unităţi fundamentale.
De exemplu, forţa se măsoară în newtoni.

1 newton = 1 N = 1 kg m s-2

N este simbolul SI pentru newton. Kilogramul, metrul şi secunda sunt mărimi fundamentale.

Cele 7 mărimi fizice fundamentale
Mărime fizicăNume unitateSimbol unitate
Lungimemetrum
Masăkilogramkg
Timpsecundăs
Intensitatea curentului electricamperA
Temperatura termodinamicăkelvinK
Cantitate de substanţămolmol
Intensitate luminoasăcandelăcd

Lungimea se măsoară în metri (m).
1 metru reprezintă lungimea drumului parcurs de lumină în vid în intervalul de 1 / 299 792 458 secunde. (1983)

Masa se măsoară în kilograme (kg).
1 kilogram reprezintă masa prototipului internațional al kilogramului confecționat dintr-un aliaj de platină și iridiu și care se păstreaza la Biroul Internațional de Măsuri si Greutăți de la Sèvres, Franța. (1889)

Timpul se măsoară în secunde (s).
1 secundă reprezintă durata a 9 192 631 770 perioade ale radiației corespunzătoare tranziției dintre două nivele de energie hiperfine ale stării fundamentale a atomului de cesiu 133. (1967)

Restul definiţiilor (pentru cei curioşi) se află aici.

Pentru exprimarea cantităţilor foarte mici şi foarte mari se foloseşte notaţia ştiinţifică.

7 710 000 000 m = 7.71 x 109 m

0.000 000 492 s = 4.92 x 10-7 s

Când lucrăm cu astfel de numere este convenabil să folosim prefixele SI ca factori de multiplicare.
Aceste prefixe reprezintă puteri de-ale lui 10.
De exemplu, 1.14 x 109 jouli = 1.14 gigajouli = 1.14 GJ [energia se măsoară în jouli (J)].

Prefixe SI des folosite
PrefixFactorSimbol
giga109G
mega106M
kilo103k
centi10-2c
mili10-3m
micro10-6`mu`
nano10-9n
pico10-12p

Tabelul complet se află aici.

De multe ori vom fi nevoiţi să exprimăm anumite mărimi fizice în alte unităţi.
De exemplu, timpul se măsoară în secunde, dar poate fi măsurat şi în minute, şi în ore, şi în zile, etc.
Ca să putem converti dintr-o unitate de măsură într-alta, folosim un factor de conversie (un raport de unităţi echivalent cu 1, unitatea).
De exemplu, 1 minut este egal cu 60 de secunde (1 min = 60 s), deci:

`{1 min} / {60 s} = {60 s} / {1 min} = 1`

Putem transforma minutele în secunde şi viceversa. Ca să transformăm 5 minute în secunde, înmulţim cele 5 minute cu factorul de conversie:

`5 min = (5 min)(1) = (5 min)({60 s} / {1 min}) = 300 s`

Minutele de la numitor şi numărător se anulează, şi rămâne 5 x 60 s = 300 s.

Trataţi valoarea şi unitatea împreună, ca o singură entitate!

`1 / 60` NU este echivalent cu `{1 min} / {60 s}` şi în NICIUN caz `1 / 60 = 1`!

vineri, 14 iunie 2013

Tutorial C++: Pointeri, Memorie Dinamică, Referinţe

Ce este un pointer?

Un pointer este o variabilă care memorează o adresă de memorie.
Un pointer se declară în felul următor:

tip * nume;
Aici tip* reprezintă tipul de dată al variabilei (obiectului) pe care pointerul îl referă.
Un pointer este un pointer deoarece el memorează o adresă şi ocupă acelaşi spaţiu de memorie cu un pointer de alt tip*.
Totuşi, asta nu înseamnă că puteţi memora adresa unui double într-un pointer int* sau să interschimbaţi adrese între pointeri de tipuri diferite.
Pe lângă memorarea adreselor, pointerii mai pot accesa şi conţinutul de la respectivele adrese. Decodificarea conţinutului se face pe baza tipului pointerului tip*.
Spaţiul de memorie pe care îl ocupă un pointer depinde de compilator şi sistemul de operare.
Exemplu de pointeri:
int * p1; // Refera un int
char * p2; // Refera un char
Aveţi grijă să iniţializaţi un pointer înainte de a-l folosi, altfel puteţi accesa zone de memorie pentru care programul vostru nu are acces, iar acest lucru poate cauza erori în program.
Puteţi iniţializa un pointer fie cu o adresă de memorie, fie cu pointerul NULL nullptr.
Acest keyword a fost introdus în noul standard C++11 şi diferă de NULL prin faptul că nu este un întreg, pur şi simplu reprezintă un pointer NULL.
NULL în C/C++ este definit ca #define NULL 0 - practic NULL este constanta zero.
Dacă compilatorul vă permite, folosiţi nullptr în loc de NULL.
Adresa unei variabile se obţine cu operatorul de referenţiere (&) (sau operatorul adresă).
ptr = &var;
Conţinutul unei adrese de memorie (stocată într-un pointer) se obţine cu operatorul de dereferenţiere (*) (sau operatorul de indirectare).
*ptr
Nu confundaţi acest operator cu steluţa (*) din declararea unui pointer! Ea face parte din tipul pointerului.
Iată un exemplu mai concret:
#include <iostream>
using namespace std;

int main()
{
    int * p1; double * p2;
    int d1 = 45; double d2 = 3.14;
    p1 = &d1;  // p1 refera variabila d1
    p2 = &d2;  // p2 refera variabila d2
    // Afisez adresele de memorie stocate in cei doi pointeri
    cout << p1 << ' ' << p2 << '\n';
    // Afisez continutul stocat la adresele de memorie
    // din cei doi pointeri
    cout << *p1 << ' ' << *p2 << '\n';
    cout << sizeof(p1) << ' ' << sizeof(p2);
    return 0;
}
Output:
0x22fef4 0x22fee8
45 3.14
4 4
Prin convenţie numerele hexazecimale sunt reprezentate cu prefixul 0x.
Operatorul sizeof(ob), unde ob reprezintă un tip (int, char, float, etc.) sau un obiect (variabilă), returnează mărimea, în bytes, a argumentului.
După cum vedeţi, pointerii ocupă 4 bytes de memorie (în sistemele de 32-biţi).

Puteţi scădea doi pointeri ca să obţineţi numărul de elemente de tipul respectiv ce încap între ei.
#include <iostream>
using namespace std;

int main()
{
    double * p1, * p2;
    double d1 = 1.1, d2 = 2.2;
    p1 = &d1; p2 = &d2;
    cout << p1 << ' ' << p2 << '\n';
    cout << p1 - p2;
    return 0;
}
Output:
0x22fef0 0x22fee8
1
Diferenţa dintre 0x22fef0 şi 0x22fee8 este 0x8, adică 8, iar 8 bytes este spaţiul de memorie pe care îl ocupă 1 double, deci rezultatul afişat este 1.
Puteţi scădea numai pointeri ce referă acelaşi tip de dată.
Dacă p1 ar fi fost int*, codul de mai sus nu ar fi compilat.

Alocarea dinamică

Când declaraţi un vector trebuie să precizaţi numărul de elemente ce-l vor alcătui.
Asta înseamnă că stabiliţi spaţiu de memorie ocupat de vector înainte de a ştii exact numărul de elemente ce va fi memorat în vectorul respectiv.
Vectorii statici pot fi ineficienţi din punct de vedere al memoriei ocupate atunci când nu se ştie exact câte elemente va memora vectorul.
De aceea C++ ne pune la dispoziţie operatorii new şi delete cu care putem aloca / dealoca memorie dinamic în timpul execuţiei programului.
Cu new se alocă (rezervă) memorie. Operatorul returnează adresa de memorie a spaţiului alocat.

tip* var = new tip;
Sau putem aloca un bloc de memorie (vector dinamic):
tip* var = new tip[nr_elem];
Nu există succes garantat când alocaţi memorie dinamic.
Operatorul new alocă memorie din zona liberă (heap).
Este posibil ca această zonă din memorie să fie ocupată de alte aplicaţii sau starea sistemului să nu permită o astfel de alocare.
În această situaţie new lansează o excepţie. Puteţi folosi (nothrow) astfel încât new să returneze pointerul NULL în caz de eşec.
tip* var = new (nothrow) tip;
Memoria alocată cu new - numai aceasta - poate fi dealocată (eliberată) cu delete.
delete var;
delete[] var; // pentru vectori
După ce aţi folosit delete pe un pointer, acesta nu mai indică către o adresă validă (respectiva adresă nu mai este rezervată pentru programul vostru), de aceea este bine să-i atribuiţi valoarea nullptr (sau NULL).
ATENŢIE: delete nu distruge variabila pointer! El eliberează spaţiul de memorie indicat de pointer prin adresa pe care o memorează.

Nu uitaţi să dealocaţi spaţiul de memorie atunci când nu mai aveţi nevoie de el!
Dacă nu dealocaţi memoria, aceasta rămâne rezervată, degeaba, pentru aplicaţia voastră, când alte aplicaţii ar putea avea nevoie de ea sau chiar programul vostru, care alocă fără să elibereze, poate rămâne fără spaţiu de lucru. Fenomenul se numeşte memory leak.
Un exemplu de alocare dinamică:
#include <iostream>
using namespace std;

int main()
{
    int* x = new int;
    *x = 98;
    cout << *x << ' ' << x;
    delete x;
    return 0;
}
Output:
98 0x7c0f70
Un vector static este practic un pointer constant. El referă numai blocul de memorie care îi este atribuit de compilator.
Numele vectorului este un pointer către primul element din vector. Exemplu:
#include <iostream>
using namespace std;

int main()
{
    int v[] = {1, 2, 3, 4, 5};
    cout << *v; // Se va afisa 1
    return 0;
}
Puteţi accesa elementele unui vector, static sau dinamic, în două moduri:
v[i]; // SAU
*(v+i);
// unde i este un intreg
Atunci când adunaţi sau scădeţi un intreg dintr-un pointer, deplasaţi pointerul peste i blocuri de memorie de tipul referit de pointer.
De exemplu, dacă un pointer (int* ptr;) referă / indică adresa 0x22feec, atunci ptr+1 va referi adresa 0x22fef0.
0x22feec + 4 = 0x22fef0 (4 este mărimea în bytes a tipului int). Vezi imaginea de mai sus.
Aşadar, putem folosi operatorii ++ şi -- pentru a parcurge un vector:
#include <iostream>
using namespace std;

int main()
{
    int v[] = {1, 2, 3, 4, 5};
    for (int i = 0; i < 5; i++)
        cout << *(v+i) << ' '; // v[i]
    return 0;
}
Din acest motiv vectorii se transmit prin referinţă.
Deoarece ei sunt nişte pointeri constanţi a căror adresă (stocată în ei) este transmisă (prin valoare) parametrului funcţiei, care este un vector.
Acel vector accesează, şi eventual modifică, conţinutul de la adresa de memorie primită.
Un exemplu cu vectori dinamici. Programul cere utilizatorului să introducă o listă de numere, iar acesta calculează şi afişează suma lor:
#include <iostream>
using namespace std;

int main()
{
    int n, suma = 0;
    cout << "Cate numere vrei sa adun? "; cin >> n;
    int * nr = new int[n];
    cout << "Scrie numerele despartite prin spatiu: ";
    for (int i = 0; i < n; i++)
        cin >> nr[i];
    // Suma
    for (int i = 0; i < n; i++)
        suma += nr[i];
    cout << "Suma lor este: " << suma;
    delete[] nr;
    return 0;
}

Pointerii constanţi sunt de două feluri:
- Pointeri care nu pot modifica datele referite (date constante), dar care pot fi modificaţi (le puteţi atribui o altă adresă);

const tip* ptr;
- Pointeri care pot modifica datele referite (date neconstante), dar care nu pot fi modificaţi (nu le puteţi atribui o altă adresă);
tip* const ptr;
- Pointeri care nu pot modifica datele referite şi nu pot fi modificaţi.
const tip* const ptr;
Exemplu:
#include <iostream>
using namespace std;

int main()
{
    const int sz = 10;
    int money = 3000;

    const int* pSz = &money;
    int* const pMoney = &money;
    const int* const ptr = &sz;

    pSz = &sz; // OK!
// *pSz = 11;  // Eroare! Nu pot modifica variabila referita
    *pMoney = 4000;   // OK!
//  pMoney = &sz;  // Eroare! Pointer constant
//  ptr = &money;  // Eroare!
//  *ptr = 13;     // Eroare
    pSz = &money;

    // Eroare! Chiar daca money nu este const
    // Pointerul n-o poate modifica
//  *pSz = 5000;

    // Iar daca se incearca modificarea unei variabile const
    // Cu un pointer neconstant, din nou eroare
    // const int* este DIFERIT de int*
    // &sz returneaza o adresa (pointer) de tip const int*
//  int* pt = &sz;
//  *pt = 17;

    return 0;
}

Pointerii pot fi parametri ai unei funcţii.
Studiaţi cu atenţie exemplele următoare.

#include <iostream>
using namespace std;

void vreauPointer(int* p)
{
    cout << "In functie *p = " << *p << '\n';
    *p = 90;  // Modific continutul de la adresa memorata in p
    cout << "Dupa modificare *p = " << *p << '\n';
    int x = 12;
    // Modificarea pointerului este vizibila doar aici
    // Deoarece variabila pointer nu este
    // transmisa prin referinta
    p = &x;
    cout << "In functie p refera " << p << '\n';
}

int main()
{
    int q = 70;
    int* ptr = &q;
    cout << "In main q = " << q << '\n';
    cout << "In main *ptr = " << *ptr << '\n';
    cout << "In main ptr refera " << ptr << '\n';
    vreauPointer(ptr);
    cout << "Dupa apel q = " << q << '\n';
    cout << "Dupa apel *ptr = " << *ptr << '\n';
    cout << "Dupa apel ptr refera " << ptr << '\n';
    return 0;
}
Output:
In main q = 70
In main *ptr = 70
In main ptr refera 0x22fef8
In funtie *p = 70
In functie p refera 0x22fef8
Dupa modificare *p = 90
Dupa modificare p refera 0x22fe6c
Dupa apel q = 90
Dupa apel *ptr = 90
Dupa apel ptr refera 0x22fef8
Pointerii pot fi transmişi prin referinţă.
#include <iostream>
using namespace std;

void vreauPointer(int* &p)  // Referinta!
{
    cout << "In functie *p = " << *p << '\n';
    *p = 90;  // Modific continutul de la adresa memorata in p
    cout << "In functie p refera " << p << '\n';
    cout << "Dupa modificare *p = " << *p << '\n';
    int x = 12;  // Aceasta variabila va fi distrusa la sfarsitul functiei
    // Modificarea pointerului este vizibila in afara
    // Deoarece variabila pointer este
    // transmisa prin referinta
    p = &x;
    cout << "Dupa modificare p refera " << p << '\n';
}

int main()
{
    int q = 70;
    int* ptr = &q;
    cout << "In main q = " << q << '\n';
    cout << "In main *ptr = " << *ptr << '\n';
    cout << "In main ptr refera " << ptr << '\n';
    vreauPointer(ptr);
    cout << "Dupa apel q = " << q << '\n';
    cout << "Dupa apel *ptr = " << *ptr << '\n';
    cout << "Dupa apel ptr refera " << ptr << '\n';
    return 0;
}
Output:
In main q = 70
In main *ptr = 70
In main ptr refera 0x22fefc
In funtie *p = 70
In functie p refera 0x22fefc
Dupa modificare *p = 90
Dupa modificare p refera 0x22fe6c
Dupa apel q = 90
Dupa apel *ptr = 4683872
Dupa apel ptr refera 0x22fe6c
Observaţi că *ptr referă o valoare ciudată. Acest lucru se întâmplă deoarece ptr memorează adresa variabilei x din funcţia vreauPointer().
Când o funcţie îşi termină execuţia toate variabilele declarate în acea funcţie (+parametrii) sunt distruse (memoria ocupată de ele este eliberată).
La respectiva adresă rămâne numai gunoi (junk), un şir de 1 şi 0 care nu are niciun sens pentru programul vostru, dar acesta îşi face datoria şi afişează interpretarea int, în acest caz, a biţilor.
Acelaşi lucru se întâmplă şi când folosiţi un pointer neiniţializat sau o variabilă neiniţializată.

Referinţe

O referinţă este un alias pentru o variabilă.
Dacă variabila reprezintă o anumită zonă de memorie, şi referinţa va reprezenta aceeaşi zonă de memorie.
Referinţele se declară cu (&).

#include <iostream>
using namespace std;

int main()
{
    int x = 6;
    int& q = x;  // q refera acelasi spatiu de memorie ca si x
    q += 5;      // Referintele se folosesc normal ca si variabilele
    cout << x;   // se va afisa 11
    return 0;
}
Referinţele trebuie iniţializate!
Nu puteţi iniţializa o referinţă cu o constantă! Trebuie să fie un obiect / variabilă.
Puteţi avea referinţe constante care referă variabile constante.
#include <iostream>
using namespace std;

int main()
{
    const int p = 5;
    const int& x = p;
    cout << x; // 5
    return 0;
}
De îndată ce a fost iniţializată, referinţa nu mai poate fi schimbată. Nu mai aveţi cum.
Referinţa se comportă ca o altă variabilă.

miercuri, 12 iunie 2013

Tutorial C++: Funcţii (Subprograme)

Ce este o funcţie?

O funcţie (subprogram) este un grup de instrucţiuni apelabil (invocabil) din alte părţi ale programului. De exemplu, main este o funcţie.
A apela o funcţie înseamnă a o executa.
Funcţiile ajută la modularizarea programului, la structurarea acestuia în unităţi logice.
O funcţie se declară în felul următor:

tip nume(lista_param); // Prototipul functiei
Exemplu:
int suma(int a, int b);
lista_param - lista de parametri, despărţiţi prin virgulă, este opţională.
Parantezele sunt obligatorii. Ele deosebesc funcţiile de alte entităţi C++ (de exemplu, variabile).
void nimic(); // functie fara parametri
Tipul void reprezintă absenţa tipului. Cu alte cuvinte, funcţiile care nu returnează nicio valoare, au tipul void.
Funcţiile pot returna valori codului apelant (locul de unde a fost apelată funcţia) prin intermediul instrucţiunii return.
După declarare, o funcţie trebuie definită undeva în program.
#include <iostream>
using namespace std;

int suma(int, int); // Declarare

int main()
{
    int x, y;
    cout << "Da-mi doua numere intregi: ";
    cin >> x >> y;
    cout << "Suma lor este " << suma(x, y);
    return 0;
}

int suma(int a, int b) // Definire
{
    int rezultat = a + b;
    // Puteam scrie direct
    // return a + b;
    return rezultat;
}
Când declaraţi o funcţie, puteţi omite numele parametrilor (aşa cum am făcut în exemplu), dar trebuie să precizaţi tipul lor.
Parametrii sunt variabile locale funcţiei (vizibile numai în blocul funcţiei).
Instrucţiunea return întrerupe execuţia funcţiei şi returnează valoarea expresiei, din dreapta, codului apelant.
Într-o funcţie puteţi avea mai multe instrucţiuni return.
Observaţi cum se apelează o funcţie: suma(x, y);. Dacă funcţia nu are parametri, se apelează doar cu nume + paranteze: funcFaraParam();.
Când execuţia unei funcţii se termină, controlul programului revine în punctul apelării şi programul îşi continuă execuţia normal.
Funcţiile void nu returnează valori, ele doar îndeplinesc o sarcină, deci nu pot avea instrucţiunea return expr;.
Puteţi însă folosi return; ca să întrerupeţi execuţia unei funcţii void.
#include <iostream>
using namespace std;

void afiseazaText() // Declarare + Definire
{
    for (int i = 0; i < 5; i++)
        cout << "Hello functions!";
}

int main()
{
    // Se va afisa de 5 ori textul:
    // Hello functions!
    afiseazaText();
    return 0;
}
Puteţi declara şi defini o funcţie în acelaşi loc, dar numai înainte de main, altfel compilatorul nu va recunoaşte funcţia.
Funcţiile void nu pot fi folosite în expresii, deoarece expresiile au în componenţa lor operatori care aşteaptă valori, ori o funcţie void nu returnează nicio valoare.
O funcţie poate avea orice număr de parametri.
Variabilele declarate într-o funcţie sunt locale, adică sunt vizibile numai în respectiva funcţie. Ele nu pot fi folosite în afara ei (valabil şi pentru parametri).
Argumentele funcţiei sunt datele (variabile, expresii, constante, etc.) transmise funcţiei şi primite de parametrii acesteia.
De exemplu, în apelul suma(x, y); argumentele sunt variabilele x şi y.

Parametrii unei funcţii pot avea valori implicite (default). Parametrii default trebuie poziţionaţi la sfârşitul listei de parametri.
După ce aţi declarat un parametru implicit, nu mai aveţi voie să declaraţi parametri normali în continuare acestuia, ci doar parametri impliciţi.

#include <iostream>
using namespace std;

double arieCerc(double raza, double PI = 3.14)
{
    return 2 * PI * raza * raza;
}

int main()
{
    cout << "Aria cercului de raza 2 este " << arieCerc(2.0) << '\n'; // PI == 3.14
    cout << "Aria cercului de raza 2 este " << arieCerc(2.0, 3.141592);
    return 0;
}
Se va afişa
Aria cercului de raza 2 este 25.12
Aria cercului de raza 2 este 25.1327
Când nu transmiteţi o valoare parametrului implicit, compilatorul va folosi valoarea implicită, dată de voi.


Supraîncărcarea (Overloading) funcţiilor

Supraîncărcaţi o funcţie atunci când definiţi mai multe versiuni ale aceleiaşi funcţii.
Funcţia trebuie să aibă acelaşi nume, dar lista de parametri trebuie să difere prin numărul parametrilor sau prin tipul parametrilor (sau ambele).
Tipul funcţiei poate fi diferit, dar nu este necesar să fie aşa.
Versiunile diferă unele de altele numai prin lista de parametri!

#include <iostream>
using namespace std;

// Aria patratului
double arie(double lungime)
{
    return lungime * lungime;
}

// Aria dreptunghiului
double arie(double lungime, double latime)
{
    return lungime * latime;
}

int main()
{
    cout << "Aria patratului de L = 2 este " << arie(2.0) << '\n';
    cout << "Aria dreptunghiului de L = 3 si l = 4 este " << arie(3.0, 4.0);
    return 0;
}
Output:
Aria patratului de L = 2 este 4
Aria dreptunghiului de L = 3 si l = 4 este 12
Funcţia arie este supraîncărcată (overloaded). Am două versiuni care diferă prin numărul de parametri.
Compilatorul se foloseşte de tipul şi numărul de argumente ca să invoce funcţia corectă.


Transmiterea prin valoare şi prin referinţă

Atunci când transmiteţi argumente (şi sunt variabile) unei funcţii, transmiteţi de fapt o copie a acelor variabile.
Aceasta este transmiterea prin valoare (pass by value).
Orice modificare a parametrilor unei funcţii este vizibilă numai în acea funcţie.
Variabilele - folosite ca argumente - rămân nemodificate.

#include <iostream>
using namespace std;

void modifica(int a)
{
    a = a + 5;
    cout << "a are valoarea: " << a << '\n';
}

int main()
{
    int x = 1;
    cout << "x inainte de apel: " << x << '\n';
    modifica(x);
    cout << "x dupa apel: " << x;
    return 0;
}
Output:
x inainte de apel: 1
a are valoarea: 6
x dupa apel: 1
O funcţie poate returna decât o singură valoare printr-un return, ca la matematică.
Uneori vrem ca o funcţie să poată returna mai multe valori. Un mod prin care putem obţine acest lucru este transmiterea prin referinţă (pass by reference).
Atunci când transmiteţi prin referinţă, parametrii funcţiei alterează direct conţinutul variabilelor argumente (nu mai există nicio copie).
Ca să transmiteţi prin referinţă folosiţi ampersand (&) între tipul parametrului şi numele acestuia.
Parametrii referinţă acceptă numai variabile. NU acceptă constante (deoarece nu pot fi alterate)!
#include <iostream>
using namespace std;

void modifica(int& a) // Nu uitati de ampersand !
{
    a = a + 5;
    cout << "a are valoarea: " << a << '\n';
}

int main()
{
    int x = 1;
    cout << "x inainte de apel: " << x << '\n';
    modifica(x);
    cout << "x dupa apel: " << x;
    return 0;
}
Output:
x inainte de apel: 1
a are valoarea: 6
x dupa apel: 6

Vectorii se transmit prin referinţă!

#include <iostream>
using namespace std;

void modifica(int v[], int l)
{
    for (int i = 0; i < l; i++)
        v[i] += 5; // v[i] = v[i] + 5;
}

int main()
{
    int w[] = {1, 2, 3, 4}, k = 4;
    modifica(w, k);

    for (int i = 0; i < k; i++)
        cout << w[i] << ' ';

    return 0;
}
Output:
6 7 8 9
Observaţi cum se transmite un vector ca parametru.
Numărul de elemente poate lipsi (valabil doar pentru prima dimensiune).
Dacă aş fi avut o matrice de 2 x 3, atunci aş fi scris:
void modifica(int v[][3], ...) ...
Veţi înţelege mai bine aceste lucruri după ce veţi învăţa ceva despre pointeri.


Funcţii recursive

O funcţie care se autoapelează se numeşte recursivă.
Aveţi grijă ca funcţia să aibă o condiţie de terminare, altfel puteţi crea o repetiţie infinită.
Parametrii funcţiilor şi variabilele locale sunt încărcate, stocate, pe Stivă (o regiune din memorie structurată pe principiul stivei, LIFO), iar în cazul unei funcţii recursive infinite, Stiva se poate umple repede (stack overflow) cauzând un crash al programului.
Factorialul unui număr poate fi calculat cu o funcţie recursivă (deşi se poate face acelaşi lucru şi cu un loop).

#include <iostream>
using namespace std;

int fact(int n)
{
    if (n == 0) // Conditia de terminare
        return 1;
    else
        return n * fact(n - 1);
}

int main()
{
    cout << fact(0) << '\n';
    cout << fact(3) << '\n';
    cout << fact(8) << '\n';
    return 0;
}
Output:
1
6
40320
Ca să înţelegeţi mai bine mecanismul recursivităţii vizionaţi acest clip de pe Youtube:


Funcţii inline

Atunci când o funcţie este apelată, parametrii şi variabilele locale sunt încărcate pe Stivă.
Acest proces consumă resurse şi timp de execuţie.
Pentru funcţiile ce efectuează puţine operaţii, apelarea poate costa mai mult timp şi spaţiu de execuţie decât dacă aceste operaţii ar fi executate direct în cod.
Din acest motiv există keyword-ul inline.
Cu inline programatorii pot cere compilatorului să insereze blocul funcţiei în punctul apelării, în loc să creeze instrucţiunile de apel.
O funcţie se declară inline în felul următor:

#include <iostream>
using namespace std;

inline double myPI()
{
    return 3.14159265359;
}

int main()
{
    cout << myPI();
    return 0;
}
Nu declaraţi inline funcţii recursive sau funcţii complexe!
Mărimea programului poate creşte considerabil.
Compilatoarele moderne de astăzi optimizează automat codul sursă.
Unele dintre ele vor refuza inline, chiar dacă programatorul le cere explicit (de exemplu, compilatoarele care optimizează mărimea programului), altele vor face automat inline anumite funcţii (compilatoarele optimizate pentru viteză), chiar dacă programatorul nu cere acest lucru.

marți, 11 iunie 2013

Tutorial C++: Vectori - Tablouri de memorie

Vectori

Un vector (array), sau tablou de memorie este o colecţie de date stocate în locaţii succesive din memorie.
Toate elementele vectorului au acelaşi tip de dată. Un vector se declară în felul următor:

tip nume[numar_elemente];
De exemplu, un vector cu 100 de întregi.
int yoyo[100];
Numărătoarea elementelor începe de la zero.
Putem accesa şi modifica un element de-al vectorului cu următoarea sintaxă:
nume[index];
De exemplu, pot atribui elementului al treilea valoarea 10.
yoyo[2] = 10;
ATENŢIE: Primul element este yoyo[0], iar ultimul este yoyo[99].
Aceşti vectori se zic statici (static arrays) deoarece numărul de elemente şi spaţiul de memorie ocupat este constant în timpul compilării. (numar_elemente trebuie să fie o constantă).
Vectorii declaraţi global, în afara oricărei funcţii, sunt iniţializaţi cu zero.
La declarare vectorii pot fi iniţializaţi, aşa cum sunt iniţializate variabilele, dar cu o sintaxă diferită.
int vec[3] = {1, 2, 3};
Sau, doar în acest caz, puteţi omite numărul de elemente:
int vec[] = {1, 2, 3};
Deoarece lungimea va fi dedusă de compilator pe baza numărului de date dintre acolade.
Parcurgerea unui vector se face cel mai simplu cu un loop, în general un for.
#include <iostream>
using namespace std;

int main()
{
    int cifrePare[] = { 0, 2, 4, 6, 8 };
    for (int i = 0; i < 5; i++)
        cout << cifrePare[i];
    return 0;
}
ATENŢIE: Accesarea elementelor din afara vectorului - cum ar fi cifrePare[5] - poate produce rezultate neaşteptate, ca instabilitatea programului sau, în cel mai rău caz, un crash al programului.

Vectori multidimensionali

Vectorii multidimensionali sunt vectori ai vectorilor. Sintaxa generală de declarare este:

tip nume[nr_elem1][nr_elem2]...[nr_elemN]
Aşa cum vedeţi, un vector poate avea oricâte dimensiuni vreţi. Totuşi, spaţiu de memorie fiind limitat, nu veţi întâlni vectori cu mai mult de 3 dimensiuni.
Un vector bidimensional poate fi imaginat ca o matrice (un tabel cu linii şi coloane).
De exemplu, matricea int mat[5][3]; are 5 linii şi 3 coloane.
În realitate, în memorie, elementele tot în ordine secvenţială sunt stocate. Vectorul (matricea) de mai sus este echivalent cu int mat[15];.
Iniţializarea este similară cu cea a vectorilor unidimensionali:
int mat[2][3] = { {1, 2, 3}, {4, 5, 6} };
Parcurgerea se face tot cu un for:
#include <iostream>
using namespace std;

int main()
{
    int cifre[2][3] = { {1, 2, 3}, {4, 5, 6} };
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 3; j++)
            cout << cifre[i][j] << ' ';
        cout << '\n';
    }
    return 0;
}
Observaţi cum se accesează elementul de pe linia i şi coloana j.
cifre[i][j];
Programul va afişa:
1 2 3
4 5 6
Primul element al matricei este cifre[0][0], adică 1.

Dacă nu vă place numărătoarea de la zero, puteţi declara vectorul cu 1 + nr_elemente, astfel încât să începeţi numărătoarea de la 1, dar să aveţi spaţiu pentru nr_elemente. Exemplu:

#include <iostream>
using namespace std;

int main()
{
    int yoyo[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    for (int i = 1; i < 10; i++)
        cout << yoyo[i] << i << ' ';
    return 0;
}
Acum indicele i coincide cu yoyo[i].
Primul element al vectorului, yoyo[0], este ignorat, şi al doilea, yoyo[1], este considerat noul prim.

vineri, 7 iunie 2013

Tutorial C++: Booleeni şi Structuri de Control

Tipul boolean

Tipul boolean sau tipul de dată logic este tipul ce are două valori: true şi false.
Acest tip este folosit în contextele booleene, acolo unde expresia este evaluată* la true sau false. De exemplu, în condiţia de la if sau while.
O variabilă de tip bool se declară normal, ca orice variabilă:

bool x = true;
În contextele booleene din C/C++, valorile pozitive sunt evaluate la true, iar ZERO este evaluat la false.
De exemplu:
if (1) cout << "TRUE";
Se va afişa mesajul TRUE deoarece 1 este interpretat ca fiind true.

Operatorii care returnează un rezultat booleean sunt operatorii relaţionali şi operatorii logici.
Operatorii relaţionali sunt:

< // Mai mic
<= // Mai mic sau egal
== // Egal
!= // Diferit
> // Mai mare
>= // Mai mare sau eagl
În general sunt folosiţi cu numere (întregi, reali), dar veţi vedea că pot fi definiţi şi pentru alte tipuri.
Opeatorii logici sunt:
&& // AND - SI LOGIC
|| // OR - SAU LOGIC
! // NOT - NEGATIE LOGICA
Operatorul AND returnează true dacă ambii operanzi sunt true.
Operatorul OR returnează true dacă cel puţin unul dintre operanzi este true.
Operatorul NOT inversează valoarea booleană a expresiei, variabilei, etc.
C++ foloseşte evaluarea scurtă.
Pentru AND: Dacă primul operand este false atunci întreaga expresie este false; nu se mai evaluează operandul al doilea.
Pentru OR: Dacă primul operand este true atunci întreaga expresie este true; nu se mai evaluează operandul al doilea.
Dintre aceşti operatori, NOT are prioritatea cea mai mare, urmat de operatorii relaţionali, apoi (în această ordine) AND şi OR.
Tabelul cu precedenţa operatorilor.

Structuri decizionale

Instrucţiunea if permite execuţia unei porţiuni de cod* doar dacă o anumită condiţie este îndeplinită. Condiţia este dată de programator.

#include <iostream>
using namespace std;

int main()
{
    int a = 4;
    if (a >= 4) {
        cout << "Hi!";
    } else {
        cout << "Bye!";
    }
    return 0;
}
Se va afişa if deoarece variabila a memorează 4, iar 4 este mai mare sau egal cu 4.
Ramura else este executată atunci când condiţia de la if nu este îndeplinită. Dacă if se execută atunci programul ignoră ramura else.
În cazul unei singure instrucţiuni (valabil pentru toate structurile de control) acoladele pot lipsi.
După else poate urma un alt if, şi un altul, până când cascada de if else se termină în else sau nu se termină în nimic, deoarece else este opţional.
#include <iostream>
using namespace std;

int main()
{
    double nr;
    cin >> nr;
    if (nr >= 2) {
        cout << "Ai introdus un numar mai mare sau egal cu 2.";
    } else if (nr < 0) {
        cout << "Ai introdus un numar negativ";
    } else {
        cout << "Ai introdus un numar din intervalul [0, 2)";
    }
    return 0;
}
Aici, ultimul else este executat numai dacă ramurile superioare nu sunt executate.
Condiţia de la if (ca şi la celelalte structuri) poate fi orice: constantă, variabile, expresie, orice se poate evalua la true sau false.
Mod de funcţionare if:
  1. Se evaluează condiţia. Dacă este true se trece la pasul următor; dacă este false se trece la pasul 3.
  2. Se execută codul din blocul if (dintre acolade) şi se trece la pasul 4.
  3. Se execută ramura else şi se trece la pasul 4.
  4. Se iese din if şi se continuă execuţia programului.

Instrucţiunea switch este, într-un fel, similară cu if. Permite execuţia anumitor instrucţiuni în funcţie de rezultatul unei expresii, variabile, etc.

#include <iostream>
using namespace std;

int main()
{
    int nr;
    cin >> nr;
    switch(nr)
    {
        case 1: cout << "Ai introdus 1"; break;
        case 2: cout << "Ai introdus 2"; break;
        default: cout << "Ai introdus un numar diferit de 1 si 2"; break;
    }
    return 0;
}
Instrucţiunea switch compară rezultatul expresiei dintre paranteze (aici este variabila nr) cu fiecare caz şi-l execută atunci când găseşte o potrivire.
Expresiile de la case trebuie să fie constante.
Fără break, switch ar evalua în continuare celelalte cazuri chiar dacă l-ar găsi pe cel potrivit.
Omiterea instrucţiunii break nu generează o eroare, deoarece este opţional.
Ultimul caz, default (implicit), se execută atunci când nu există potriviri cu celelalte cazuri.
Un exemplu care arată cum puteţi valorifica lipsa break-ului:
#include <iostream>
using namespace std;

int main()
{
    int nr;
    cin >> nr;
    switch(nr)
    {
        case 1: case 2: case 3: case 4: case 5: case 6: case 7:
            cout << "Ai introdus ziua a " << nr << "-a"; break;
        default:
            cout << "Te rog sa introduci numarul valid al unei zile";
    }
    return 0;
}
Să zicem că nr este 2. Se execută cazul 2, apoi, deoarece nu există break, se trece la 3, apoi la 4, ... până la 7 unde există break şi se iese din switch.

Structuri iterative - Bucle - Loop-uri

Instrucţiunea while repetă o porţiune de cod până când condiţia devine falsă. Dacă condiţia nu devine falsă la un moment dat, while va continua să ruleze (până când programul este oprit forţat de programator / user).

#include <iostream>
using namespace std;

int main()
{
    int nr;
    cout << "Ca sa inchizi programul scrie 0.\n";
    cin >> nr;
    while (nr != 0) { // Cat timp nr nu este 0
        cout << nr * 2 << '\n';
        cin >> nr;
    }
    return 0;
}
Condiţia de la while, în acest exemplu, este nr != 0.
Atunci când folosim loopuri trebuie să ne asigurăm că aceste condiţii vor deveni false în cele din urmă, ca să evităm repetiţiile infinite.
În exemplul meu, decizia de a opri programul (care în fond înseamnă oprirea iteraţiei) îi aparţine utilizatorului, prin acel cin >> nr; din while.
Mod de funcţionare while:
  1. Se evaluează condiţia. Dacă este true se trece la pasul următor. Dacă este false se trece la pasul 4.
  2. Se execută codul din blocul while (dintre acolade).
  3. Se trece la pasul 1.
  4. Se iese din while şi se continuă execuţia programului.

O variaţie a structurii while este do { } while(conditie); Spre deosebire de while, codul în do while este executat cel puţin o dată indiferent de condiţie.

#include <iostream>
using namespace std;

int main()
{
    bool conditie = false;
    do {
        cout << "In while :)";
    } while (conditie);
    return 0;
}
Se va afişa In while :) deoarece evaluarea se face la final.
Observaţi ; după while. Este obligatoriu.

Instrucţiunea for repetă de un anumit număr de ori o porţiune de cod.

#include <iostream>
using namespace std;

int main()
{
    for (int i = 1; i <= 10; i++) {
        cout << i << ' ';
    }
    return 0;
}
Se va afişa: 1 2 3 4 5 6 7 8 9 10.
for (initializare; conditie; incrementare)
Instrucţiunea for are trei părţi:
  • La iniţializare se declară (şi se iniţializează) variabila (sau variabilele) contor (folosită la numărat).
  • La conditie avem o expresie de terminare a iteraţiei.
  • La incrementare (sau decrementare) variabila contor este modificată astfel încât condiţia să poată deveni la un moment dat falsă.
Toate cele trei părţi sunt opţionale. Nu este obligatoriu să declaraţi variabila contor în for, deşi dacă o declaraţi acolo, ea va fi vizibilă numai în blocul for.
#include <iostream>
using namespace std;

int main()
{
    for (int i = 10; i > 0; i-=2) {
        cout << i << ' ';
    }
    return 0;
}
Se va afişa: 10 8 6 4 2. Mod de funcţionare:
  1. Se iniţializează variabilele (Această parte se execută o singură dată).
  2. Se evaluează condiţia. Dacă este true se trece pasul următor. Dacă este false se trece la pasul 5.
  3. Se execută codul din blocul for.
  4. Se execută instrucţiunea de la incrementare.
  5. Se iese din for şi se continuă execuţia programului.

Prin cod se înţelege o instrucţiune sau grup de instrucţiuni.
A evalua este echivalent cu a executa.

duminică, 14 aprilie 2013

Tutorial Python - Instrucţiuni de Control Flow

Instrucţiunea if

Instrucţiunea if execută o anumită porţiune de cod numai dacă este îndeplinită o condiţie. Condiţia este o expresie booleeană.
>>> x = 0
>>> if x < 0:
 print('Negativ')
elif x == 0:
 print('Neutru')
elif x == 1:
 print('Unitate')
else:
 print('Pozitiv mai mare ca 1')

 
Neutru
Python foloseşte indentarea (alineatul) pentru a delimita blocurile de cod.
Instrucţiunile din blocul if se scriu cu 4 spaţii mai interior. În exemple nu apare aşa deoarece Python inserează TAB-uri în loc de spaţii, iar Blogspot se pare că are o problemă cu aceste TAB-uri.
În exemplu am o singură instrucţiune sub if, print('Negativ'). Nu trebuie să număraţi spaţiile deoarece Python indentează automat când apăsaţi ENTER după cele două puncte (:).
Instrucţiunea elif este o prescurtare de la else if.
Instrucţiunile elif şi else sunt opţionale. else apare întotdeauna ultima.
Semnificaţia este următoarea: Dacă condiţia de la if este adevărată se execută instrucţiunile din blocul if, altfel se trece la ramura următoare, else sau elif, şi se reia procesul.
După ce aţi terminat de scris o instrucţiune if în IDLE, apăsaţi de două ori ENTER ca s-o executaţi.

Instrucţiunile for şi while

Instrucţiunea for este folosită pentru a parcurge o secvenţă de numere (progresie aritmetică) sau pentru a parcurge elementele unei colecţii (liste, stringuri, seturi, etc.).
>>> txt = 'tutorialeplusplus'
>>> for ch in txt:
 print(ch, end=' ')

 
t u t o r i a l e p l u s p l u s 
end=' ' înseamnă că fiecare afişare este despărţită de spaţiu (implicit este end='\n').
Iată un exemplu cu for şi if.
>>> for ch in txt:
 if ord(ch) > ord('e'):
  print(ch, end=' ')
 else:
  print(ch.upper(), end=' ')

  
t u t o r i A l E p l u s p l u s 
Un exemplu cu o progresie aritmetică generată de funcţia range.
>>> for i in range(5):
 print(i)

 
0
1
2
3
4
Funcţia (de fapt este o clasă...dar voi ajunge şi acolo) range ia trei parametri (ultimul fiind opţional): start, stop, step (step [pas] semnifică raţia progresiei) SAU ia un singur parametru (ca-n exemplu) stop (start=0 şi step=1).
>>> for nr in range(10, 0, -1):
 print(nr, end=' ')

 
10 9 8 7 6 5 4 3 2 1 
Parcurgerea progresiilor aritmetice cu range este mult mai eficientă decât echivalentul în while.
>>> mylist = ['a', 1, True, 'b', 0]
>>> ln = len(mylist)
>>> for i in range(ln):
 print(mylist[i])

 
a
1
True
b
0
Instrucţiunea while repetă o porţiune de cod cât timp condiţia este adevărată.
>>> q = 1
>>> while q < 10:
 print(q)
 q += 1 # q = q + 1

 
1
2
3
4
5
6
7
8
9
Şi un alt exemplu, în care creez o listă pornind de la un string şi afişez acel string invers:
>>> st = list('stiva')
>>> while len(st) > 0:
 print(st.pop(), end='')

 
avits
Nu uitaţi că funcţia pop returnează şi apoi elimină elementul de la sfârşitul listei.

Instrucţiunile break, continue şi else pentru loopuri

Un loop (buclă) reprezintă o structură repetitivă (for sau while).
Instrucţiunea break întrerupe execuţia unui loop.
>>> for i in range(10):
 if i == 5:
  break
 print(i)

 
0
1
2
3
4
Instrucţiunea continue ignoră restul codului din loop şi continuă cu următoarea iteraţie.
>>> for i in range(10):
 if i == 3 or i == 5 or i == 7:
  continue
 print(i)

 
0
1
2
4
6
8
9
Instrucţiunile loop (repetitive) pot avea o ramură else care se execută atunci când loop-ul este epuizat, fie pentru că a parcurs toate elementele unei colecţii, fie condiţia a devenit falsă.
Pe scurt: Loopul NU este întrerupt cu break.
>>> for i in range(2, 10):
 for x in range(2, i):
  if i % x == 0:
   print(i, ' nu este numar prim')
   break
 else:
  # Dupa epuizarea forului se executa else
  print(i, ' este numar prim')

  
2  este numar prim
3  este numar prim
4  nu este numar prim
5  este numar prim
6  nu este numar prim
7  este numar prim
8  nu este numar prim
9  nu este numar prim
Atenţie! Acest else este asociat cu un for nu cu if.
Priviţi ce s-ar fi afişat fără else.
>>> for i in range(2, 10):
 for x in range(2, i):
  if i % x == 0:
   print(i, ' nu este numar prim')
   break
 # Aceasta instructiune se va executa de fiecare data
 print(i, ' este numar prim')

 
2  este numar prim
3  este numar prim
4  nu este numar prim
4  este numar prim
5  este numar prim
6  nu este numar prim
6  este numar prim
7  este numar prim
8  nu este numar prim
8  este numar prim
9  nu este numar prim
9  este numar prim
Deci, pentru structurile repetitive, else se execută numai când loopul se termină normal, fără întrerupere cu break.

Instrucţiunea pass

Instrucţiunea pass nu face nimic. Este instrucţiunea vidă.
Se foloseşte acolo unde se cere o instrucţiune din punct de vedere sintactic, dar nu este nevoie de una.
Exemplu, while infinit.
>>> while True:
 pass # Apasati Ctrl+C ca sa opriti executia
Mai multe informaţii:
>>> help('for')
>>> help('while')

Acum ar trebui să fiţi în stare să scrieţi programe (scripturi) simple.
Scrieţi în Python Shell un program care calculează suma primilor 20 de termeni ai şirului lui Fibonacci.
Primii doi termeni sunt 1, iar umătorii se calculează conform formulei

fib_n = fib_n-1 + fib_n-2
Vezi rezultatul.
Vezi soluţia.

Tutorial Python - Stringuri (Şiruri de caractere)

Stringurile sunt şiruri de caractere Unicode (Python 3). Sunt immutable (imuabile; nu pot fi alterate).
Avantajul oferit de Unicode este că fiecare caracter, din orice limbă, şi fiecare simbol are asociat un număr de ordine (ordinal).
Înainte de Unicode existau doar 256 de ordinali cu care puteai să reprezinţi caracterele. Unicode a rezolvat această problemă.
Putem afla numărul de ordine (pentru caracterele uzuale acesta este codul ASCII) al unui caracter cu funcţia ord(ch) şi putem afla caracterul corespunzător unui ordinal cu funcţia chr(nr).

>>> ord('ă')
259
>>> ord('ف')
1601
>>> ord('∫')
8747
>>> ord('0')
48
>>> ord('A')
65
>>> chr(9001)
'〈'
>>> chr(8752)
'∰'
>>> chr(97)
'a'
>>> chr(1608)
'و'
>>> chr(25384)
'挨'
În Python caracterele nu au un tip propriu. Pur şi simplu sunt stringuri de lungime 1.
Stringurile se declară fie cu ghilimele fie cu apostrofuri. Eu, de regulă, folosesc apostrofuri.
Dacă le declaraţi cu apostrofuri puteţi folosi ghilimele în string. Dacă le declaraţi cu ghilimele puteţi folosi apostrofuri în string.
Sau puteţi folosi secvenţe escape (\' şi \").
>>> txt = 'Vi \'imbecillia\' asseverent to ostenditur "objectioni" argumentis.'
>>> txt
'Vi \'imbecillia\' asseverent to ostenditur "objectioni" argumentis.'
>>> alttxt = "Videmur vim quo seorsim' petebat."
>>> alttxt
"Videmur vim quo seorsim' petebat."
Interpretorul afişează stringurile aşa cum le-am introdus. Dacă vrem să fie afişate corespunzător folosim funcţia print.
>>> print(txt)
Vi 'imbecillia' asseverent to ostenditur "objectioni" argumentis.
>>> print(alttxt)
Videmur vim quo seorsim' petebat.
Puteţi folosi secvenţa escape \n pentru a insera un rând nou în string şi puteţi folosi \ pentru a indica interpretorului că stringul continuă pe rândul următor (altfel dacă apăsaţi ENTER interpretorul va evalua expresia).
>>> txt = 'Vul student quaeque brachia nos divelli.\
Ha ex alterius locusque\n\
ins idias\n  formalis ii mutuatur judiciis.'
>>> print(txt)
Vul student quaeque brachia nos divelli.Ha ex alterius locusque
ins idias
  formalis ii mutuatur judiciis.
>>> txt
'Vul student quaeque brachia nos divelli.Ha ex alterius locusque\nins idias\n  formalis ii mutuatur judiciis.'
Observaţi că acel backslash nu apare în string.
O alternativă la \n este folosirea a trei ghilimele sau a trei apostrofuri.
În acest caz rândurile noi din interpretor se traduc în \n în string.
În exemplu, folosesc un backslash la început (şi la sfârşit) ca să previn inserarea unui nou rând în string.
Puteam de asemenea să încep imediat după apostrofuri şi să nu mai pun acel backslash.
>>> txt = '''\
Essentiae infinitae ad imaginata vi videretur to tantaeque obversari.
Debiliora in ab opinantem priusquam perfectae.
Desumptas apparebat effecerit dubitandi objective id ex du profundum.\
'''
>>> print(txt)
Essentiae infinitae ad imaginata vi videretur to tantaeque obversari.
Debiliora in ab opinantem priusquam perfectae.
Desumptas apparebat effecerit dubitandi objective id ex du profundum.
Puteţi afişa un string aşa cum îl introduceţi dacă adăugaţi un r în faţa acestuia (raw string).
>>> rw = r'This \n is a\' raw "string"'
>>> print(rw)
This \n is a\' raw "string"
Putem accesa caractere individuale aşa cum accesam elementele listelor şi, de asemenea, putem folosi notaţia slice pentru a "extrage" substringuri (vezi liste).
>>> txt = 'Corpus omne perseverare in statu suo quiescendi vel movendi uniformiter in directum, nisi quatenus a viribus impressis cogitur statum illum mutare.'
>>> len(txt) # Lungimea stringului
147
>>> txt[0]
'C'
>>> txt[-1]
'.'
>>> txt[-2]
'e'
>>> txt[7:23]
'omne perseverare'
>>> txt[:6]
'Corpus'
>>> txt[-7:-1]
'mutare'
Stringurile nu pot fi modificate!
>>> txt[0] = 'T'
Traceback (most recent call last):
  File "<pyshell#66>", line 1, in <module>
    txt[0] = 'T'
TypeError: 'str' object does not support item assignment
Operatorul + concatenează două stringuri, iar operatorul * repetă un string. Ambii operatori returnează un string nou.
>>> law = 'Lex'
>>> word = law + ' I'
>>> print(word)
Lex I
>>> print(law * 7)
LexLexLexLexLexLexLex
Tipul str (string) conţine numeroase metode (funcţii) ce implementează operaţiile comune cu stringuri.
Acest exemplu vă prezintă câteva din aceste metode.
>>> lex3 = 'Actioni contrariam semper et æqualem esse reactionem: sive corporum duorum actiones in se mutuo semper esse æquales et in partes contrarias dirigi.'
>>> sub = lex3[8:36]
>>> sub
'contrariam semper et æqualem'
>>> # Returneaza un string cu primul caracter capitalizat si restul lowercase
>>> sub.capitalize()
'Contrariam semper et æqualem'
>>> # Returneaza numarul de aparitii al unui string
>>> lex3.count('semper')
2
>>> # Returneaza indicele unui substring
>>> lex3.index(sub)
8
>>> # Returneaza true daca toate caracterele sunt lowercase
>>> sub.islower()
True
>>> # Elimina spatiile initiale si finale
>>> '   fara spatii    '.strip()
'fara spatii'
>>> # Returneaza true daca caracterul este cifra
>>> '1'.isdigit()
True
Mai multe informaţii pe siteul Python.
În Python până şi constantele string sunt obiecte! ('1'.isdigit())
Puteţi testa dacă un string se află într-un alt string cu operatorul in.
>>> 'et' in lex3
True
>>> 'A' in lex3
True
>>> sub in lex3
True
Stringurile pot fi formatate cu funcţia format.
>>> username = 'Newton'
>>> password = 'inertia'
>>> 'Parola lui {0} este "{1}"'.format(username, password)
'Parola lui Newton este "inertia"'
Câmpurile {0} şi {1} ţin locul (în ordine) parametrilor funcţiei format.
Mai multe detalii despre aceste câmpuri găsiţi pe siteul Python.
Şi nu uitaţi de:
>>> help('str')

sâmbătă, 13 aprilie 2013

Tutorial Python - Seturi şi Dicţionare

Seturi (Mulţimi)

Un set (mulţime) este o colecţie neordonată de iteme de orice tip immutable.
Elementele apar într-un singur exemplar (nu există duplicate) şi nu apar în ordine.
Set-urile suportă operaţiile standard de reuniune, intersecţie, diferenţă, şi diferenţă simetrică.
Un set se defineşte ca şi o listă, dar cu acolade în loc de paranteze pătrate.
>>> A = {4}
>>> vid = set()
>>> A
{4}
>>> vid
set()
Setul vid (mulţimea vidă) se defineşte folosind funcţia set(). Sintaxa {} defineşte un dicţionar vid.
Tot cu această funcţie puteţi crea un set pornind de la o listă set(lst) unde lst este o listă.
Putem crea un set pornind de la un string.
>>> litere = set('tutorialeplusplus')
>>> litere
{'u', 't', 's', 'r', 'p', 'e', 'a', 'o', 'l', 'i'}
Observaţi că elementele sunt unice, iar ordinea nu se păstrează.
Putem adăuga elemente noi la un set. Dacă valoarea adăugată există deja, nu se întâmplă nimic: no-op (no operation).
>>> a = {1}
>>> a.add(2)
>>> a
{1, 2}
>>> a.add(3)
>>> a
{1, 2, 3}
>>> a.add(2)
>>> a
{1, 2, 3}
Putem folosi funcţia update să adăugăm mai multe elemente (fie de la alte seturi, fie de la liste).
>>> a.update({4,7,9})
>>> a
{1, 2, 3, 4, 7, 9}
>>> a.update({1, 10}, {13, 11})
>>> a
{1, 2, 3, 4, 7, 9, 10, 11, 13}
>>> a.update([40, 42, 50])
>>> a
{1, 2, 3, 4, 7, 9, 10, 11, 13, 40, 42, 50}
Această funcţie acceptă orice număr de parametri (seturi, liste, tuple, etc.).
Eliminăm elemente cu funcţiile discard şi remove.
Atunci când remove încearcă să elimine un element inexistent va lansa excepţia (eroarea) KeyError, în timp ce discard nu face nimic (no-op).
>>> a.discard(11)
>>> a
{1, 2, 3, 4, 7, 9, 10, 13, 40, 42, 50}
>>> a.discard(11)
>>> a
{1, 2, 3, 4, 7, 9, 10, 13, 40, 42, 50}
>>> a.remove(13)
>>> a
{1, 2, 3, 4, 7, 9, 10, 40, 42, 50}
>>> a.remove(13)
Traceback (most recent call last):
  File "<pyshell#31>", line 1, in <module>
    a.remove(13)
KeyError: 13
Cu funcţia clear() putem şterge toate elementele setului.
Operaţiile standard mulţimilor le suportă şi tipul set.
>>> a = {1, 2, 3, 4}
>>> b = {3, 4, 5, 6}
>>> a.union(b) # Reuniune
{1, 2, 3, 4, 5, 6}
>>> a | b
{1, 2, 3, 4, 5, 6}
>>> a.intersection(b) # Intersectie
{3, 4}
>>> a & b
{3, 4}
>>> a.difference(b) # Diferenta
{1, 2}
>>> a - b
{1, 2}
>>> a.symmetric_difference(b) # Diferenta simetrica
{1, 2, 5, 6}
>>> a ^ b
{1, 2, 5, 6}
Observaţi că am pus şi operatorii specifici fiecărei operaţii. Atât funcţiile cât şi operatorii returnează seturi noi.
Puteţi testa dacă un element se află într-un set cu operatorul in (vezi liste).
De asemenea, există şi funcţiile issubset şi issuperset care testează dacă un set este un subset sau un superset al unui alt set.
>>> a = {1,  2}
>>> b = {1, 2, 3, 4}
>>> a.issubset(b)
True
>>> b.issuperset(a)
True
>>> a.add(7)
>>> a.issubset(b)
False
>>> b.issuperset(a)
False
În contextele booleene seturile vide sunt False, iar cele nevide sunt True.
Mai multe informaţii:
>>> help('set')

Dictionaries (Dicţionare)

Dicţionarul este un tip de dată compus. Este o mulţime neordonată de perechi key - value (cheie - valoare).
Dicţionarele sunt optimizate pentru extragerea valorilor atunci când se cunosc cheile. Aceste chei pot fi obiecte de tip immutable (stringuri, numere, tuple care conţin numai elemente immutable).
Listele nu pot fi chei deoarece pot fi modificate. Dicţionarele se definesc cu acolade. Cheile şi valorile asociate se precizează folosind sintaxa key:value.
Perechea {} defineşte un dicţionar vid.
>>> bob = {'a': 1, 'b': 2, 'c':3}
>>> vid = {}
>>> bob
{'a': 1, 'c': 3, 'b': 2}
>>> vid
{}
Apoi putem folosi notaţia de la liste (numai că de data aceasta în loc de indici numerici avem chei) ca să extragem valorile din dicţionar. Dacă o cheie nu există va fi lansată o eroare.
>>> bob['b']
2
>>> bob['a']
1
>>> bob[2]
Traceback (most recent call last):
  File "<pyshell#6>", line 1, in <module>
    bob[2]
KeyError: 2
Puteţi adăuga elemente noi folosind sinxtaxa dictionar[key] = value.
Puteţi modifica elemente existente folosind aceeaşi sintaxă. Cu del se pot şterge elemente.
>>> bob[2] = 'doi'
>>> bob
{2: 'doi', 'a': 1, 'c': 3, 'b': 2}
>>> bob['c'] = 5
>>> bob
{2: 'doi', 'a': 1, 'c': 5, 'b': 2}
>>> del bob[2]
>>> bob
{'a': 1, 'c': 5, 'b': 2}
Dintr-un dicţionar se pot extrage cheile, valorile şi itemele în liste.
>>> list(bob.keys())
['a', 'c', 'b']
>>> list(bob.items())
[('a', 1), ('c', 5), ('b', 2)]
>>> list(bob.values())
[1, 5, 2]
Folosiţi operatorul in pentru a testa dacă o cheie (nu o valoare!) se află în dicţionar.
>>> 'a' in bob
True
>>> 1 in bob
False
În contextele booleene dicţionarele vide sunt False, iar cele nevide sunt True.
Informaţii suplimentare:
>>> help('dict')

vineri, 12 aprilie 2013

Tutorial Python - Liste şi Tuple

Liste

  • Lista este un tip de dată compus.
  • Este o colecţie de iteme.
  • Itemele (elementele) pot fi de orice tip.
  • Este un tip de dată mutable - poate fi modificat
Itemele listelor se pun intre paranteze pătrate. Listele se declară în felul următor:
>>> mylist = [1, 'a', '%', 2.57, 9+3j]
>>> mylist
[1, 'a', '%', 2.57, (9+3j)]
Stringurile (şirurile de caractere) în Python se declară cu ghilimele sau cu apostrofuri.
Obiectele listei sunt numerotate de la zero, deci primul element este mylist[0].
Lista păstrează ordinea elementelor. Un element poate apărea de mai multe ori într-o listă.
De asemenea, Python permite indici negativi cu semnificaţia
mylist[-n] == mylist[len(mylist) - n]
>>> mylist[0] # Primul item al listei
1
>>> mylist[-1] # Ultimul item al listei
(9+3j)
>>> mylist[4]  # Ultimul item al listei
(9+3j)
>>> mylist[5]
Traceback (most recent call last):
  File "<pyshell#5>", line 1, in <module>
    mylist[5]
IndexError: list index out of range
Dacă depăşiţi dimensiunea listei, Python va lansa eroarea IndexError.
Funcţia len(ob) returnează mărimea / dimensiunea obiectului ob (trebuie să fie o colecţie).
>>> len(mylist)
5
Putem tăia o listă, adică putem să extragem părţi dintr-o listă folosind sintaxa slice:
>>> mylist[1:3]
['a', '%']
>>> mylist[0:3]
[1, 'a', '%']
>>> mylist[:3]
[1, 'a', '%']
>>> mylist[3:]
[2.57, (9+3j)]
>>> mylist[:]
[1, 'a', '%', 2.57, (9+3j)]
Operatorul slice (:) returnează întotdeauna o listă nouă.
Sintaxa mylist[start:end] are semnificaţia: Returnează itemele din intervalul [start, end). Fără mylist[end].
Atunci când start lipseşte, Python ia în considerare valoarea implicită zero.
Iar când end lipseşte se ia considerare valoarea len(mylist).
În exemplu, mylist[:3] returnează toate itemele începând de la primul (0) până la al patrulea (3), dar fără acest element, iar mylist[3:] returnează toate elementele începând cu al patrulea (3) până la sfârşit.
Dacă ambele valori lipsesc, operatorul slice returnează o copie a listei.
Listele pot fi modificate. Putem adăuga elemente noi la listă cu operatorul de concatenare +.
>>> mylist = [3]
>>> mylist = mylist + ['1', 6.7]
>>> mylist
[3, '1', 6.7]
Operatorul + creează o nouă listă în memorie formată din concatenarea celor două liste, apoi atribuie noua listă variabilei mylist.
Dacă memoria este limitată atunci nu folosiţi această sintaxă. Folosiţi funcţiile append şi extend.
>>> mylist.append(True)
>>> mylist
[3, '1', 6.7, True]
>>> mylist.extend(['^', 7.0])
>>> mylist
[3, '1', 6.7, True, '^', 7.0]
Atenţie! Funcţia extend adaugă elementele argumentului (iterabil; are sau poate genera o secvenţă de iteme) la listă, în timp ce funcţia append adaugă argumentul la listă (chiar dacă este iterabil). Exemplu:
>>> mylist = [1, 2, 3, 4, 5]
>>> len(mylist)
5
>>> mylist.append(['one', 'two'])
>>> mylist
[1, 2, 3, 4, 5, ['one', 'two']]
Listele pot avea ca elemente alte liste, după cum vedeţi. Elementele acestor liste se accesează uşor:
>>> mylist[-1]
['one', 'two']
>>> mylist[-1][0]
'one'
>>> mylist[-1][1]
'two'
Elementele listei pot fi modificate.
>>> mylist = ['a', 'b', 5, 7]
>>> mylist[0] = False
>>> mylist
[False, 'b', 5, 7]
Putem verifica dacă un element se află în listă folosind operatorul in.
>>> 'b' in mylist
True
>>> 'a' in mylist
False
Putem afla de câte ori un element se află în listă.
>>> mylist = ['c', 'b', 's', 'ab', 'b', 'c']
>>> mylist.count('c')
2
Şi putem să aflăm index-ul unui item.
>>> mylist.index('ab')
3
>>> mylist.index('b')
1
>>> mylist.index('b', 2)
4
>>> mylist.index('abc')
Traceback (most recent call last):
  File "<pyshell#44>", line 1, in <module>
    mylist.index('abc')
ValueError: 'abc' is not in list
Funcţia index ia trei parametri: valoarea căutată, [start, [stop]] reprezentând capetele intervalului pe care se face căutarea: [start, stop).
Am pus parametrii între paranteze pătrate (aşa veţi întâlni şi-n documentaţiile Python) ca să subliniez faptul că sunt opţionali.
Când stop lipseşte se caută de la start până la sfârşit.
Dacă elementul nu există în listă, funcţia va genera eroarea ValueError.
Un alt mod de inserare a valorilor într-o listă este prin funcţia insert.
>>> mylist = [1, 2, 'a']
>>> mylist.insert(0, 'E')
>>> mylist
['E', 1, 2, 'a']
>>> mylist.insert(2, 'two')
>>> mylist
['E', 1, 'two', 2, 'a']
Aceasta ia doi parametri: primul reprezintă indexul unde va fi inserat elementul, iar al doilea reprezintă elementul inserat.
Funcţia insert inserează în faţă, elementele listei fiind deplasate la dreapta pentru a face loc itemului adăugat.
Ca să ştergem un element dintr-o listă putem folosi operatorul del.
>>> mylist = [-1, -2, ':)', ':(']
>>> mylist
[-1, -2, ':)', ':(']
>>> del mylist[-1]
>>> mylist
[-1, -2, ':)']
>>> del mylist[0]
>>> mylist
[-2, ':)']
Atunci când un element este eliminat dintr-o listă, celelalte elemente sunt mutate astfel încât să acopere "gaura" creată. Ordinea itemelor se păstrează.
>>> mylist[0]
-2
>>> mylist[-1]
':)'
Dacă nu cunoaşteţi poziţia unui item în listă, puteţi folosi funcţia remove.
>>> mylist = ['t', 'r', 4.5, True]
>>> mylist.remove('t')
>>> mylist
['r', 4.5, True]
>>> mylist.remove('t')
Traceback (most recent call last):
  File "<pyshell#19>", line 1, in <module>
    mylist.remove('t')
ValueError: list.remove(x): x not in list
Pe lângă remove mai există şi funcţia pop. Aceasta returnează elementul înainte de a-l elimina.
>>> mylist = ['a', 'b', 'patru', 'last']
>>> mylist.pop()
'last'
>>> mylist
['a', 'b', 'patru']
>>> mylist.pop(0)
'a'
>>> mylist
['b', 'patru']
Fără argument, pop returnează şi elimină ultimul element.
Se pot elimina iteme de pe alte poziţii dacă transmitem indicele corespunzător. Şi aici elementele vor fi mutate pentru a acoperi "gaura" creată.
Ca să eliminăm toate elementele dintr-o listă avem două opţiuni:
>>> mylist[:] = [] # [] este lista vida (fara elemente)
Sau cu funcţia clear.
>>> mylist.clear()
>>> mylist
[]
În contextele booleene listele nevide sunt True, iar cele vide sunt False.
>>> if []:
 print(True)
else:
 print(False)

 
False
>>> if [1]:
 print(True)
else:
 print(False)

 
True
În final nu uitaţi de >>> help('list'). Poate fi de mare ajutor atunci când uitaţi ceva.

Tuple

Un tuple (n-am găsit o traducere mai bună) este o listă immutable (imuabilă, care nu poate fi modificată). Se definesc ca listele numai că se folosesc paranteze rotunde.
>>> tupy = ('^_^', '©', 8, 9, 6)
>>> tupy
('^_^', '©', 8, 9, 6)
>>> tupy[0]
'^_^'
>>> tupy[-1]
6
Puteţi folosi operatorul slice, puteţi concatena (aceste operaţii creează tuple noi), puteţi verifica dacă un element se află într-un tuple, dar nu-l puteţi modifica.
Aşadar funcţiile append, extend, remove, pop, insert nu există într-un tuple.
Un tuple este mai rapid decât o listă atunci când aveţi o secvenţă şi vreţi doar să iteraţi prin ea.
Un tuple poate fi folosit la dicţionare pe post de key (asta dacă elementele pe care le conţine sunt immutable: stringuri, numere, tuple, etc.).
Ca să creaţi un tuple cu un singur element puneţi virgulă după acel element (altfel Python va crede că sunt doar două paranteze şi le va ignora).
>>> tupy = ('one',)
>>> tupy
('one',)  # Avem tuple :)
>>> tupy = ('one')
>>> tupy
'one'     # Oops! String!
La fel ca listele, un tuple vid este False, iar un tuple nevid este True (în contexte booleene).
Puteţi transforma un tuple într-o listă folosind funcţia list(ob) sau puteţi transforma o listă într-un tuple folosind funcţia tuple(ob).
Pentru mai multe detalii aveţi >>> help('tuple').

joi, 11 aprilie 2013

Tutorial Python - Calculatorul Python - Variabile

Python ca şi calculator

Aşa cum v-am spus, Python poate fi folosit ca şi calculator. Deschideţi Shellul (IDLE) şi calculaţi ceva, să zicem:
>>> 3 * 2 + 1
7
Regulile sunt ca la matematică. Puteţi folosi paranteze ca să alteraţi ordinea evaluării.
>>> 3 * (2 + 1)
9
Spaţiile albe nu sunt obligatorii. Eu le introduc pentru claritate.
Operatorii aritmetici sunt: +, -, / , *, % , //, **
Operatorul modulo % calculează restul împărţirii a două numere.
>>> 5 % 2
1
Operatorul împărţire întreagă // returnează partea întreagă a împărţirii a două numere.
>>> 9 // 2
4
>>> 9 // -2
-5
Operatorul / realizează împărţirea normală şi returnează un float.
>>> 5 / 2
2.5
Iar ultimul operator ** ridică la putere.
>>> 2 ** 3
8
>>> 4 ** (1/2) # Radical din 4
2.0
Comentariile în Python se introduc cu simbolul #. Comentariile sunt ignorate de interpretor, rolul lor este de a clarifica porţiuni de cod, deşi fiecare foloseşte comentariile cum vrea.
Python permite folosirea notaţiei ştiinţifice:
>>> 2e3 # 2 * 10**3
2000.0
>>> 4E-3 # 4 * 10**-3
0.004
>>> 1.23e9 # 1.23 * 10**9
1230000000.0
>>> 1e2 # 10**2
100.0
e sau E înseamnă, în notaţia ştiinţifică, 10 la puterea.
Variabila built-in _ (prezentă în modul interactiv) reţine ultima valoare calculată. Este utilă atunci când folosiţi Python pe post de calculator.
Nu atribuiţi nicio valoare acestei variabile deoarece veţi crea una nouă, locală, care o va masca pe cea originală şi nu veţi mai obţine efectele dorite (decât dacă restartaţi Shellul).
>>> 2 + 4
6
>>> 8 * _
48
>>> _
48
Ca să putem folosi funcţiile matematice (sin, cos, log, etc.) trebuie să importăm modulul (built-in) math folosind această instrucţiune import math.
Apoi puteţi folosi instrucţiunea help('math') ca să aflaţi mai multe informaţii despre acest modul.
>>> import math
>>> math.sin(math.pi/2)  # Argumentul trebuie sa fie in radiani
1.0
>>> math.log(math.e)  # Logaritm natural (in baza e)
1.0
>>> math.hypot(3, 5)  # Calculeaza ipotenuza conform Teoremei lui Pitagora
5.8309518948453
Observaţi că trebuie să scrieţi de fiecare dată numele modului atunci când folosiţi obiecte definite în acesta. Dacă vă este lene staţi liniştiţi deoarece există o soluţie.
Puteţi folosi instrucţiunea from modul import nume unde modul este numele modului din care importaţi, iar nume este numele pe care-l importaţi.
Ca să importaţi toate numele dintr-un modul folosiţi from modul import *.
Nu recomand acest lucru deoarece pot apărea conflicte între numele din modulul respectiv şi numele din modulul vostru (să zicem că aveţi funcţia sin definită de voi şi funcţia sin definită în math. Conflict!).
Există o soluţie şi pentru această problemă: Alias-urile.
>>> from math import sin as sn
>>> from math import pi as PI
>>> sn(PI/2)
1.0
Python caută modulele în toate folderele ce apar în sys.path. Ca să vedeţi conţinutul sys.path, importaţi modulul sys.
>>> import sys
>>> sys.path
['', 'C:\\Python33\\Lib\\idlelib', 'C:\\Windows\\system32\\python33.zip', 'C:\\Python33\\DLLs', 'C:\\Python33\\lib', 'C:\\Python33', 'C:\\Python33\\lib\\site-packages']
Python este case-sensitive. Literele mari diferă de cele mici.

Variabile

Variabilele în Python sunt simplu de definit. Trebuie doar să atribuiţi o valoare unui nume.
>>> pret = 300
>>> pret
300
Nu puteţi folosi un nume (variabilă) înainte de a-l defini. Acest lucru va genera eroarea NameError.
>>> a
Traceback (most recent call last):
  File "<pyshell#16>", line 1, in 
    a
NameError: name 'a' is not defined
Variabilele pot fi formate din cifre, litere, underscore. Nu pot începe cu cifre.
Puteţi atribui simultan o valoare mai multor variabile.
>>> a = b = c = 4
>>> b
4
Puteţi atribui valoarea unei expresii.
>>> x = 4 + 7 * 3
>>> x
25
Şi puteţi folosi variabilele în expresii, împreună cu funcţii şi alte obiecte.
Python determină tipul de dată al variabilei pe baza informaţiei memorată în acea variabilă şi reţine intern tipul de dată al fiecărei variabile.
Puteţi iniţializa mai multe variabile pe acelaşi rând folosind sintaxa:
>>> a, b, c = 7, 2, 4
>>> b
2
>>> a
7
>>> c
4
Dacă vreţi să atribuiţi o progresie de numere unor variabile puteţi folosi funcţia range.
>>> a, b, c, d = range(4)
>>> a
0
>>> b
1
>>> c
2
>>> d
3
Puteţi distruge o variabilă folosind operatorul del:
>>> del a # Obs: Nu puteti sterge o variabila nedefinita
>>> a
Traceback (most recent call last):
  File "<pyshell#5>", line 1, in <module>
    a
NameError: name 'a' is not defined

Tutorial Python - Numere şi Booleeni

În Python fiecare valoare are un tip de dată, dar atunci când definiţi o variabilă nu trebuie să precizaţi tipul deoarece Python îşi dă singur seama de acest lucru pe baza valorii atribuite variabilei.
Orice lucru din Python este un obiect. Obiectul este un concept abstract (va fi definit mai bine când voi ajunge la OOP), dar... ce trebuie să ştiţi este că obiectele au atribute şi metode (funcţii).
Atributele şi metodele se accesează folosind operatorul punct (.) (Ex: math.pi). Obiectele pot fi atribuite variabilelor şi pot fi transmise ca argumente funcţiilor.
Pe lângă tipurile pe care le veţi întâlni în acest tutorial, trebuie să ştiţi că mai există şi altele, cum ar fi tipul clasă, tipul modul, tipul funcţie, tipul fişier, tipul cod compilat (până şi codul compilat are tip), etc.
Aceste lucruri sunt posibile deoarece - REŢINEŢI - în Python există numai obiecte.

Numere

Aţi văzut deja exemple. Numerele în Python sunt:
  • Întregi: -4, 1, 68, 78964, -45
  • Float (Numere Reale): 2.234, -234.4, 1.0
  • Fracţii (Numere Raţionale): 1/2, 4/5, 2/3
  • Numere Complexe: 1+4j, 2-3j, 5j
>>> import fractions
>>> x = fractions.Fraction(4, 5) # Defineste o fractie
>>> x
Fraction(4, 5) # 4 / 5
>>> 2 * x
Fraction(8, 5)
>>> y = fractions.Fraction(1, 2)
>>> x + y
Fraction(13, 10)
>>> fractions.Fraction(1, 0)
Traceback (most recent call last):
  File "<pyshell#15>", line 1, in <module>
    fractions.Fraction(1, 0)
  File "C:\Python33\lib\fractions.py", line 167, in __new__
    raise ZeroDivisionError('Fraction(%s, 0)' % numerator)
ZeroDivisionError: Fraction(1, 0)
Ca să puteţi folosi fracţiile trebuie să importaţi modulul fractions.
Fracţiile suportă şi ele aceleaşi operaţii matematice ca şi celelalte numere. Python nu permite împărţirea prin zero.
Fracţiile vor fi aduse automat la forma ireductibilă de către obiectul Fractions.
Numerele complexe sunt definite în Python. Numerele imaginare au sufixul j sau J.
Nu este necesar să importaţi vreun modul ca să le puteţi folosi.
>>> z = 3 + 4j
>>> q = 9 - 7j
>>> z + q
(12-3j)
>>> z - q
(-6+11j)
>>> z * q
(55+15j)
>>> z / q
(-0.007692307692307695+0.4384615384615385j)
>>> q.conjugate() # Conjugatul lui q
(9+7j)
>>> z.real # Partea reala
3.0 
>>> z.imag # Partea imaginara
4.0
>>> x = complex(1, 2) # Un alt mod de a crea un nr complex
>>> x
(1+2j)
Nu există limită pentru lungimea întregilor. Pot fi oricât de lungi vreţi (trebuie doar să aveţi destulă memorie).
>>> wow = 239502357286547637657436598234983928647836745836473856738402390417309720953498564836502479104739846537845619823675498734572039470943579034578634578353785387583457384583745873458345810123131091928301297394730291093
>>> wow
239502357286547637657436598234983928647836745836473856738402390417309720953498564836502479104739846537845619823675498734572039470943579034578634578353785387583457384583745873458345810123131091928301297394730291093
Numerele float au o precizie de 15 zecimale, dar aveţi grijă deoarece operaţiile cu float nu sunt întotdeauna precise. De exemplu:
>>> import math
>>> math.tan(math.pi / 4)
0.9999999999999999 # Ar fi trebuit sa fie 1.0
Puteţi folosi funcţia abs ca să aflaţi valoarea absolută a unui număr şi funcţia round ca să rotunjiţi un float.
>>> z = 2+2j
>>> abs(z)
2.8284271247461903
>>> p = -3
>>> abs(p)
3
>>> i = 9j
>>> abs(i)
9.0
>>> x = 2.678
>>> round(x)
3
>>> round(x, 1)
2.7
>>> round(x, 2)
2.68
>>> round(x, 3)
2.678
Al doilea parametru al funcţiei round reprezintă precizia rotunjirii (la câte zecimale să fie rotunjit numărul).

Booleeni

Valorile booleene apar în instrucţiunile decizionale, în loop-urile while, for, practic în orice context boolean (expresiile de la care Python aşteaptă o valoare booleană).
O valoare booleană poate fi True sau False.
Valorile nenule sunt considerate True, iar cele nule sunt considerate False.
Din acest motiv, practic orice expresie poate fi folosită într-un context boolean.
Operatorii care returnează valori booleene sunt: >, <, ==, >=, <=, not
>>> 1 < 2
True
>>> 1 > 5
False
>>> 2 == 2 # echivalent 
True
>>> 9 <= 10 # mai mic sau egal
True
>>> 11 >= 11 # mai mare sau egal
True
>>> 1.0 == 1
>>> (1/2) / (1/2) == 1
True
not 1 < 2
False
Operatorul not inversează valoarea de adevăr a expresiei.
Nu confundaţi operatorul de atribuire = cu operatorul de egalitate == !
Operatorii logici în Python sunt and şi or.
>>> True and True
True
>>> False and True
False
>>> True or False
True
>>> False or False
False
AND returnează TRUE dacă ambii operanzi sunt TRUE.
OR returnează TRUE dacă unul dintre operanzi este TRUE.
Vom folosi aceşti operatori la structurile de control.