Am nevoie să numere întregi nesemnate

Pluralismul într-un singur cap - este schizofrenia.
Nahum Korzhavin

Fără numere întregi fără semn, în principiu, este posibil de a gestiona. De fapt, dacă avem brusc nevoie de a utiliza un număr mai mare decât 2147483647 (acest lucru este maximul pentru 32 de biți număr întreg, maxim 32 de biți numere întregi fără semn - este 4294967295), trebuie să te duci doar pentru numerele întregi pe 64 de biți. De-a lungul acestui traseu am mers la limbajul Java. În ea nu există nici un întreg fără semn. Trăim într-o lume perfectă, care ar fi fost create exact în funcție de gusturile noastre, numere întregi fără semn ar trebui să fie excluse din limba viselor noastre. Dar noi trebuie să pună cu mediul existent, care este adesea reprezentat pe Windows. O utilizare completă WinAPI numere întregi fără semn. Dacă dorim cooperarea deplină a programelor noastre cu Windows, nu puteți renunța la numere întregi fără semn.

Care este dimensiunea maximă a fișierului, care poate rula programul? Încearcă să înțelegi. Versiunile pe 32 de biți de lucru suport pentru Windows cu fișiere 4Gb lungime. Convins de acest lucru prin citirea descrierii funcțiilor WinAPI readfile: Dar ia în considerare funcția de poziționare (Borland C ++ 5.5) Fișier: După cum puteți vedea, numere întregi fără semn în definirea acestor funcții nu sunt utilizate. semnat doar numere întregi. Prin urmare, Borland C ++ 5.5 pur și simplu nu ne permite să lucreze cu fișiere mai mult de 2 GB! Sau trebuie să ai uzhatsya în dorințele lor?

Limitarea dimensiunea fișierului 2Gb - nu problema cea mai urgentă. Mai ales în perioada de tranziție de la 64 de biți de calcul. Cu toate acestea, nevoia de interacțiune cu forțele WinAPI au numere întregi fără semn de limbă.

Codurile de caractere - numere întregi fără semn sau semnate?

Probabil că nu există nici un astfel de programator care ar fi niciodată în viața mea nu a recurs la tabelul de simboluri. Să presupunem că ne-a luat pentru a afla codul, de exemplu, litera „I“ în 1251. Această scrisoare are o pagină de cod 255. Scrierea codul în program: Este scris: Ce dracu '? După cum se poate avea un cod de simbol negativ? Tabela de simboluri nici un cod negativ! Din păcate, codurile caracter negativ - adevărul amar. C'est la vie. S-ar părea, nu vă faceți griji, trebuie să vă amintiți despre acest lucru simplu. Dar să presupunem că aveți o matrice, în cazul în care fiecare literă corespunde unui anumit număr întreg. Din păcate, nu poți. Având în vedere că „I“ are un cod de -1, atunci acest lucru va apela la elementul de matrice la indexul -1. Aceasta nu este o problemă pentru limbi cum ar fi PHP. Dar ce să facă în limbi, cum ar fi C / C ++. Nu, încă nu le place să lucreze cu indicii negative ale unei matrice. Și, după cum preodelet? Poate adopta un truc: Dar, în general, compilatorul nu poate garanta că masele «ar0» și «Ar 1» vor fi plasate în locații de memorie adiacente. C / C ++ standard (într-adevăr, orice altă limbă!) Nu garantează plasarea variabilelor învecinate în același cartier și în memorie. Și de ce face acest lucru, nu au soluții normale? Încearcă să meargă în jurul valorii. Se pare: idioțenie! Ce un om genial făcut coduri negative? Poate că acest lucru este tot pentru că Stroustrup? Într-adevăr, în constantele C caracter pur, cum ar fi „I“ au un int, si C ++ - tip char. Variabile și constante de tip char nu pot avea valori mai mari decât 127. Dar, dacă acestea sunt de tip int, int poate permite valori mai mari de 127! Verificați cu compilator C pură - TinyCC. Obținem: Deci, Stroustrup are o scuză: C, în aceeași mizerie. Pentru a da vina pe Ritchie. Aici este predarea lui voluntară și mărturisire (Kernighan, Ritchie, «C Programming Language“, ediția a doua):

Fie că variabilele de tip char iconic (semnătură) sau nesemnate, în funcție de sistemul particular, dar pe ecran și imprimarea de caractere sunt întotdeauna coduri pozitive.

Asta e. Cu alte cuvinte, pe care doriți să - stick la regulile de circulație pravostronnego. Și puteți - dreapta, totul depinde de țara respectivă.

Ei bine, avem ceva de făcut atunci când nu există standarde de jure, dar există standarde de facto? Noi încercăm să concureze mai mult: Ptiu, în cele din urmă! Dar cum cu atenție și au fost împrăștiate raclete! În cele din urmă, dacă nu chiar așa coduri de caractere sunt negative, și tabele de referință scrise ceva cu totul diferit, putem rescrie pur și simplu tabel. Acum puteți respira ușor? Nu, așteptați. Cu siguranță, nu! Primul disponibil sub tutorialul brațul pe C, care ne spune. Codurile de caractere variază de la 0 la 255! Cum așa? Am văzut doar că personajele sunt stocate în variabile de char, care au un domeniu -128-127! Să vedem afișat pe simbolurile ecran în codificarea 866: va apărea pe consola: Ce avem? constantele șir constau din elemente de tip char (interval de valori - -128-127), dar în aceste linii, ar trebui să scrie datele 0-255? Asta-i drept! Limbajul C nu prevede un cod de intrare negativ în interiorul constante șir!

Și asta nu e tot. Atunci când siruri de caractere de sortare trebuie să utilizați fie propria funcție comparație (care ia în considerare faptul că „eu“ mai mare „z“), sau considerate a fi sortate siruri de caractere ca unsigned char.

Ce concluzie se poate trage din investigațiile noastre? Este posibil să se facă codurile de caractere ar fi pozitiv? De fapt, există limbi în cazul în care nu există astfel de probleme. De bază pentru că totul este în regulă!

Ieșirile văzut astfel (în funcție de dactilografiere).
  • Tastat static, numere întregi fără semn în limba nu există. În acest caz, va trebui să plătească ceva. Pentru a stoca 8-biți de caractere, în acest caz nu este necesară în teoria de 9 biți, dar, în practică, 16. UNICODE caractere de 16 biți vor fi stocate în 32 de biți. Excelent dacă acest preț - este de până la creatorii de limbi viitoare.
  • Tastat numere întregi, static fără semn în limba acolo. Apoi, constantele simbolice pot fi char destul de nesemnate! Acesta este unul dintre „pentru“ argument în dreptul contestă existența unor numere întregi fără semn.
  • dactilografiere dinamică. Într-o astfel de limbă nu contează cu adevărat ce tip de una sau de cealaltă valoare. În cazul în care programul este scris, «o =«I»;“, atunci variabila «o» va avea un tip șir de caractere, iar valoarea va fi, aceasta este «I». Și dacă trebuie să știți codul pentru acest personaj? Deci, pentru acest lucru în astfel de limbi există un val funcție (), care returnează codul de caractere. Iar atunci când scrie funcții în mâinile noastre: Vreau - și toate codurile vor fi pozitive, vreau să - exact opusul. În acest caz, in plus „detaliile tehnice“ sunt pur și simplu ascunse și nu sunt vizibile pentru programator.

O comparație între numere întregi semnate și nesemnate

Dacă da dreptul la viață este un întreg fără semn, atunci trebuie să fim pregătiți pentru alte trucuri. De exemplu, acest lucru: În ciuda faptului că 1 = 0 „este întotdeauna adevărat, iar ciclul nu este întreruptă, așa cum era de așteptat, și continua. Și, prin urmare, se produce o buclă infinită în care «i» se schimba valoarea de la 4294967295 la 0. Motivul - compararea incorectă a întreg fără semn și a semnat atunci când verificarea stării continue a ciclului. Aceasta este ceea ce am considerat în paragraful precedent.

Comportamentul pe preaplin

Problemele descrise mai sus asociate cu un comportament de program incorect în cazul unui preaplin. Depășește la nivel de hardware, este posibil să se urmărească. program de calculator Arhitectura IBM / 360/370 UE preusmativalos întrerupe pe preaplin. Arhitectura x86 este un steag special de caz. unde CF și pavilioanelor semnalului revărsare a avut loc în operații aritmetice. S-ar părea, nimic nu împiedică să reacționeze la ele. Dar, în C / C ++ nu apare, cauza este cel mai probabil neobhomost portabilitate cross-platform. La urma urmei, această limbă ar trebui să se comporte în același mod pe sute de platforme, inclusiv calculatoare din anii 1970: PDP, DEC, ICL. limbajul C are originea la începutul anilor 1970 și să se comporte în același mod ca și în urmă cu 40 de ani. Prin urmare, compilatoare moderne ignora reacția capabilități de hardware la overflow.

Și aici este limba Ruby, care nu au în spatele codul de moștenire al Vechiului Testament, nu își poate permite să funcționeze în mod corespunzător. În Ruby „extinderea“ există o celulă de preaplin pentru stocarea valorii variabile astfel încât să includă o valoare nouă fără pierderi. Ie "On the fly" schimbare de biți de calcul. Acesta este motivul pentru care Ruby nu reușește testul pentru a calcula factorial. Cele mai multe limbi au „pauze“ în 12! sau 13! Acestea includ Pascal. care este lăudat pentru ei „ically matematic.“

Concluzii privind utilizarea numerelor întregi fără semn.

Ele sunt mai utile pentru limbile tipuri statice. Iată-le:
  • În limba de viitor încă mai bine să aibă numere întregi fără semn.
  • În cazul în care generează excepții de preaplin. Programul nu trebuie înghițit în tăcere astfel de erori. Erorile nu ar trebui să fie redus la tăcere!
  • Atunci când se atribuie numere întregi valori incorecte trebuie să fie, de asemenea, a generat o excepție.
  • Este necesar să se facă o comparație validă de numere întregi semnate și fără. Comparată int unsigned A și int B, apoi
    • Dacă un bit semnificativ este 1 (adică A> 2147483647), A> B
    • Dacă B MSB este 1 (adică, B este negativă), atunci A> B
    • În caz contrar, cei mai semnificativi biți ai ambelor numere sunt egale cu 0, iar rezultatul comparație A> B va fi corect.

Lecturi suplimentare pe acest subiect

# 9608; # 9608; # 9608; # 9608; # 9608; # 9608; # 9608; # 9608; # 9608; # 9608; # 9608; # 9608; # 9608; # 9608; 3 (33.3%)

În limbajul de programare Schema pus în aplicare un astfel de număr de model care corespunde concepte matematice cele mai moderne. Fiecare număr este complex. Cu toate acestea, ea are alte stări. De exemplu - este 3 și numărul întreg și numărul real și un număr complex și +3. Să spunem că toate numerele întregi sunt reale limbaj. Toate numerele reale sunt complexe. Deși sunt utilizate în reprezentarea internă a diferitelor formate, acest model este complet transparent pentru programator - numere diferite pot participa la o expresie fără o conversie explicită. Excepțiile pot fi doar numere întregi - într-un număr de punere în aplicare care sunt lungi și pot conține orice număr de cifre. Acest lucru în timpul operațiunilor, ceea ce duce la număr întreg nu este specificat poate duce la Îndatoririle overflow pentru urmărirea acestei situații se află pe programator.

„Variabila«ui»este tratat ca un întreg semnat Da, și apoi ambuscade Dar evitați -!. Destul de o sarcină fezabilă.“

Dimpotrivă, este „i“ este tratat ca un întreg fără semn.

Da, ai dreptate, eu sunt acum corect

Din păcate, nu poți. Având în vedere că „I“ are un cod de -1, atunci acest lucru va apela la elementul de matrice la indexul -1. Aceasta nu este o problemă pentru limbi cum ar fi PHP. Dar ce să facă în limbi, cum ar fi C / C ++?

char s [256]; char * s1 = (s [127]); // și indexurile din ambele părți asupra sănătății

Imbecilitate! Ce un om genial făcut coduri negative?

Brad, nu înțeleg ce problema este, char semnat - va fi negativ char, nesemnat - nu va. Și contează cu adevărat în ce fel genul?

Și cu privire la problema de preaplin.
gCC:
6.53 Funcții încorporate pentru a face operatii aritmetice cu Overflow Verificare

Următoarele funcții încorporate permit efectuarea de operații aritmetice simple, împreună cu verificarea dacă operațiunile înecată.
- Built-in Funcția: bool __builtin_add_overflow (tipul1 a, tipul2 b, type3 * res)
- Built-in Funcția: bool __builtin_sadd_overflow (int a, int b, res * int)
- Built-in Funcția: bool __builtin_saddl_overflow (lung int a, int b lung, lung res * int)
.
Și acest lucru:
Zăngăni oferă următoarele aritmetice verificate comenzilor interne de shell:
__builtin_add_overflow bool (tipul1 x, y type2, Type3 * sum);
__builtin_sub_overflow bool (tipul1 x, y type2, Type3 * dif);
__builtin_mul_overflow bool (tipul1 x, y type2, Type3 * prod);
.