Astaamaha aan dhabta ahayn ee Noocyada dhabta ah, ama ka taxdar REAL

Daabacaadda ka dib qodobbada ku saabsan sifooyinka wax ku qorida PostgreSQL, faallooyinka ugu horreeya waxay ku saabsan yihiin dhibaatooyinka ku shaqeynta tirooyinka dhabta ah. Waxaan go'aansaday inaan si degdeg ah u eego koodka weydiimaha SQL ee ii diyaar ah si aan u arko inta jeer ee ay isticmaalaan nooca REAL. Waxaa soo baxday in marar badan la isticmaalo, horumariyayaashuna had iyo jeer ma fahmaan khataraha ka dambeeya. Taasna inkasta oo ay jiraan maqaallo badan oo wanaagsan oo ku saabsan internetka iyo Habré oo ku saabsan astaamaha kaydinta tirooyinka dhabta ah ee xusuusta kumbuyuutarka iyo la shaqeynta iyaga. Sidaa darteed, maqaalkan waxaan isku dayi doonaa inaan ku dabaqo sifooyinka noocaas ah PostgreSQL, waxaana isku dayi doonaa inaan si degdeg ah u eego dhibaatooyinka la xiriira iyaga, si ay u sahlanaato horumarinta su'aalaha SQL.

Dukumeentiga PostgreSQL ayaa si kooban u sheegaya: "Maareynta khaladaadkaas oo kale iyo faafintooda inta lagu jiro xisaabinta waa mawduuca laanta xisaabta iyo sayniska kombiyuutarka, oo aan halkan lagu daboolin" (iyadoo si xikmad leh u tixraacaya akhristaha heerka IEEE 754). Waa maxay nooca khaladaadka halkan loola jeedo? Aynu u falanqeyno sida ay u kala horreeyaan, waxaana dhawaan soo bixi doonta sababta aan mar kale qalinka u qaatay.

Aan soo qaadano tusaale ahaan codsi fudud:

********* ЗАПРОС *********
SELECT 0.1::REAL;
**************************
float4
--------
    0.1
(1 строка)

Natiijo ahaan, ma arki doono wax gaar ah - waxaan heli doonaa 0.1 la filayo. Laakiin hadda aan barbar dhigno 0.1:

********* ЗАПРОС *********
SELECT 0.1::REAL = 0.1;
**************************
?column?
----------
f
(1 строка)

Ma sinna! Waa maxay mucjisooyinka! Laakiin intaa ka sii badan. Qof ayaa dhihi doona, waan ogahay in REAL ay si xun u dhaqanto jajabyada, markaa waxaan geli doonaa tirooyinka dhan halkaas, wax walbana hubaal way fiicnaan doonaan iyaga. Haa, aynu u tuurno lambarka 123 REAL:

********* ЗАПРОС *********
SELECT 123456789::REAL::INT;
**************************
   int4   
-----------
123456792
(1 строка)

Oo waxay noqotay 3 kale! Taasi waa sidaas, kaydka xogta ayaa ugu dambeyntii illoobay sida loo tiriyo! Mise wax baynu is fahmin? Aynu ogaano.

Marka hore, aynu xasuusano maadada. Sidaad ogtahay, nambar kasta oo jajab tobanle ah waxa lagu kordhin karaa toban awoodood. Markaa, lambarka 123.456 wuxuu la mid noqonayaa 1*102+2*101+3*100+4*10-1+5*10-2+6*10-3. Laakin kombuyuutarku wuxuu ku shaqeeyaa nambaro qaab binary ah, sidaas darteed waa in lagu matalo qaabka ballaarinta awoodaha laba. Sidaa darteed, lambarka 5.625 ee binary wuxuu u taagan yahay 101.101 wuxuuna la mid noqonayaa 1*22+0*21+1*20+1*2-1+0*2-2+1*2-3. Oo haddii awoodaha togan ee laba had iyo jeer bixiyaan tiro dhan jajab tobanle (1, 2, 4, 8, 16, iwm), markaas kuwa taban wax walba waa ka sii adag yihiin (0.5, 0.25, 0.125, 0,0625, iwm). Dhibaatadu waa taas Jajab kasta oo jajab tobanle ah looma matali karo jajab aan dhammaad lahayn. Markaa, 0.1-kayaga caanka ah ee qaabka jajabka binary wuxuu u muuqdaa sida qiimaha xilliyeed 0.0(0011). Sidaa darteed, qiimaha ugu dambeeya ee lambarkan ee xusuusta kombuyuutarku wuu is beddeli doonaa iyadoo ku xidhan qoto dheer.

Hadda waa waqtigii la xasuusan lahaa sida lambarada dhabta ah loogu kaydiyaa xusuusta kombuyuutarka. Guud ahaan, tirada dhabta ahi waxay ka kooban tahay saddex qaybood oo waaweyn - calaamad, mantissa iyo jibbaaro. Calaamaddu waxay noqon kartaa mid lagu daray ama laga jaray, markaa hal xoogaa ayaa loo qoondeeyay. Laakiin tirada jajabyada mantissa iyo jibbaarada waxaa lagu go'aamiyaa nooca dhabta ah. Marka, nooca REAL, dhererka mantissa waa 23 bits (hal xoogaa ah oo u dhigma 1 ayaa si toos ah loogu daraa bilowga mantissa, natiijaduna waa 24), jibbaarkuna waa 8 bits. Wadarta guud waa 32 bits, ama 4 bytes. Iyo nooca DOUBLE PRECISION, dhererka mantissa wuxuu noqon doonaa 52 bits, jibbaarkuna wuxuu noqonayaa 11 bits, wadar ahaan 64 bits, ama 8 bytes. PostgreSQL ma taageerto saxnaanta sare ee lambarada dhibcaha sabbaynaya.

Aynu ku xidhno nambarka jajab tobanle ee 0.1 labada nooc ee saxda ah iyo kuwa labanlaaban. Maaddaama calaamadda iyo qiimaha jibbaarada ay isku mid yihiin, waxaan diiradda saari doonaa mantissa (waxaan si ula kac ah uga tagayaa sifooyinka aan caddayn ee kaydinta qiyamka jibbaha iyo eber qiyamka dhabta ah, maadaama ay adkeynayaan fahamka oo ay ka jeediyaan nuxurka. dhibaatada, haddii aad xiisaynayso, eeg heerka IEEE 754). Maxaan helaynaa? Xariiqda sare waxaan ku siin doonaa "mantissa" nooca REAL (iyadoo la tixgalinayo wareega ugu dambeeya ee 1 lambarka ugu dhow, haddii kale waxay noqon doontaa 0.099999 ...), iyo xariiqda hoose - waayo, nooca DOUBLE PRECISION:

0.000110011001100110011001101
0.00011001100110011001100110011001100110011001100110011001

Sida cad kuwani waa laba tiro oo gebi ahaanba kala duwan! Sidaa darteed, marka la barbardhigo, tirada kowaad waxaa lagu dhejin doonaa eber, sidaas darteed, way ka weynaan doontaa kan labaad (iyadoo la tixgelinayo wareegyada - kan ku calaamadsan geesinimada). Tani waxay sharraxaysaa madmadowga tusaalayaashayada. Tusaalaha labaad, lambarka si cad loo cayimay ee 0.1 waxa lagu tuuray nooca DOUBLE PRECISION, ka dibna marka la barbar dhigo tiro ka mid ah nooca REAL. Labaduba waa la dhimay isku nooc, waxaanan haysanaa waxa aan kor ku aragno. Aan wax ka beddelno weydiinta si wax walba ugu dhacaan meeshooda:

********* ЗАПРОС *********
SELECT 0.1::REAL > 0.1::DOUBLE PRECISION;
**************************
?column?
----------
t
(1 строка)

Runtii, annagoo samaynayna laba-dhimista tirada 0.1 ilaa RUN IYO LABAAD PRECISION, waxaan helnaa jawaabta halxiraalaha:

********* ЗАПРОС *********
SELECT 0.1::REAL::DOUBLE PRECISION;
**************************

      float8       
-------------------
0.100000001490116
(1 строка)

Tani waxay sidoo kale sharraxaysaa tusaalaha saddexaad ee sare. Lambarka 123 waa mid fudud suurtagal maaha in mantissa lagu dhejiyo 24 bits (23 cad + 1 maldahan). Tirada ugu badan ee geli karta 24-bit waa 224-1 = 16. Sidaa darteed, nambarkayaga 777 waxa lagu soo koobay midka ugu dhow 215

********* ЗАПРОС *********
SELECT 123456789::DOUBLE PRECISION::INT;
**************************
   int4   
-----------
123456789
(1 строка)

Waa intaas. Waxaa soo baxday in aysan jirin mucjisooyin. Laakiin wax kasta oo lagu sharraxay waa sabab wanaagsan oo looga fikiro inta aad runtii u baahan tahay nooca REAL. Waxaa laga yaabaa in faa'iidada ugu weyn ee isticmaalkeeda ay tahay xawaaraha xisaabinta oo leh luminta saxda ah ee la yaqaan. Laakin tani miyay noqonaysaa dhacdo caalami ah oo sabab u noqon karta isticmaalka joogtada ah ee noocan ah? Ha ka fikirin.

Source: www.habr.com

Add a comment