ALGO25 / BLOG

Capcana lui abs la cea mai mică valoare negativă

Verifică dacă modulul unui întreg încape în tipul rezultatului. Explică asimetria intervalului cu semn și conversia făcută înainte de abs.

Modulul unui număr negativ este pozitiv în matematică, dar tipul numeric al programului trebuie să îl poată reprezenta. În configurația obișnuită cu int pe 32 de biți, intervalul este de la -2147483648 la 2147483647. Modulul primei valori este 2147483648, care nu încape în același int.

Intervalul cu semn este asimetric

Există o valoare negativă în plus față de valorile strict pozitive. De aceea simpla operație de schimbare a semnului nu este validă pentru orice întreg din întregul domeniu al tipului. Problema nu ține numai de funcția abs; și o negare directă poate cere un rezultat nereprezentabil.

Nu rula un asemenea caz și nu interpreta rezultatul observat drept regulă a limbajului. O operație al cărei rezultat nu este reprezentabil nu oferă comportamentul matematic pe care îl urmărești. Alege domeniul acceptat sau reprezentarea înainte de calcul.

Conversia trebuie făcută înainte

Dacă x este int pe 32 de biți și long long poate reprezenta 2147483648, convertești mai întâi x la long long și apoi îi calculezi modulul. Atribuirea rezultatului lui abs(x) într-un long long este prea târzie dacă apelul a fost deja evaluat pentru int.

Aceeași idee apare la scăderea a-b. Chiar dacă vrei să aplici abs rezultatului, diferența trebuie să fie reprezentabilă înainte de apel. Conversia unui operand înaintea scăderii poate muta calculul în tipul mai larg, dacă limitele acestuia sunt suficiente.

Pentru un int de 32 de biți cu semn, minimul este -2147483648, iar maximul 2147483647. Modulul minimului, 2147483648, depășește maximul.Pentru un int de 32 de biți cu semn, minimul este -2147483648, iar maximul 2147483647. Modulul minimului, 2147483648, depășește maximul.Mărește schema ↗

Un tip mai larg nu este o soluție infinită

Și long long are o valoare minimă proprie al cărei modul poate să nu încapă în long long. Dacă cerința permite întregul său domeniu, trebuie o reprezentare potrivită pentru magnitudine sau un tratament separat. Nu repeta automat aceeași conversie presupunând că există mereu un tip semnat mai mare.

În problemele școlare, limitele sunt de obicei date explicit. Pentru valori între -10^9 și 10^9, de exemplu, modulul încape într-un întreg semnat care poate reprezenta 10^9. Justificarea trebuie făcută după limitele problemei, nu după câteva teste mici.

Ce testezi

Verifică zero, un pozitiv și un negativ cu același modul. Apoi analizează pe hârtie limita minimă acceptată și diferența maximă dintre două intrări. Testarea nu înlocuiește demonstrarea faptului că operațiile intermediare sunt reprezentabile.

Revezi tipurile de date, funcțiile matematice și operatorii.

Întrebări frecvente

De ce poate eșua abs pentru cea mai mică valoare int?

Domeniul obișnuit al unui întreg cu semn conține o valoare negativă în plus. Modulul minimului poate depăși maximul pozitiv al aceluiași tip, deci rezultatul nu este reprezentabil.

Ajută atribuirea rezultatului lui abs într-un long long?

Nu dacă operația a fost deja evaluată într-un tip prea îngust. Convertește operandul înainte de negare sau de calculul modulului, într-un tip care poate reprezenta rezultatul.

Este long long suficient pentru modulul oricărui long long?

Nu. Minimul propriu al lui long long are aceeași problemă de asimetrie. Pentru întregul domeniu trebuie aleasă o reprezentare capabilă să păstreze acea magnitudine, de exemplu una fără semn, cu conversii corecte.