వాస్తవ రకాలు యొక్క అవాస్తవ లక్షణాలు, లేదా రియల్‌తో జాగ్రత్తగా ఉండండి

ప్రచురణ తర్వాత వ్యాసాలు PostgreSQLలో టైప్ చేసే లక్షణాల గురించి, మొదటి వ్యాఖ్య వాస్తవ సంఖ్యలతో పని చేయడంలో ఉన్న ఇబ్బందుల గురించి. నాకు అందుబాటులో ఉన్న SQL ప్రశ్నల కోడ్‌ను వారు ఎంత తరచుగా రియల్ రకాన్ని ఉపయోగిస్తున్నారో చూడటానికి నేను త్వరితగతిన పరిశీలించాలని నిర్ణయించుకున్నాను. ఇది చాలా తరచుగా ఉపయోగించబడుతుందని మరియు డెవలపర్లు దాని వెనుక ఉన్న ప్రమాదాలను ఎల్లప్పుడూ అర్థం చేసుకోలేరు. కంప్యూటర్ మెమరీలో వాస్తవ సంఖ్యలను నిల్వ చేసే లక్షణాల గురించి మరియు వాటితో పని చేయడం గురించి ఇంటర్నెట్‌లో మరియు హబ్రేలో చాలా మంచి కథనాలు ఉన్నప్పటికీ ఇది వాస్తవం. అందువల్ల, ఈ కథనంలో నేను PostgreSQLకి అటువంటి లక్షణాలను వర్తింపజేయడానికి ప్రయత్నిస్తాను మరియు వాటితో సంబంధం ఉన్న సమస్యలను త్వరగా పరిశీలించడానికి ప్రయత్నిస్తాను, తద్వారా SQL ప్రశ్న డెవలపర్‌లు వాటిని నివారించడం సులభం అవుతుంది.

PostgreSQL డాక్యుమెంటేషన్ క్లుప్తంగా ఇలా పేర్కొంది: "అటువంటి లోపాల నిర్వహణ మరియు గణన సమయంలో వాటి ప్రచారం అనేది గణితం మరియు కంప్యూటర్ సైన్స్ యొక్క మొత్తం శాఖకు సంబంధించిన అంశం మరియు ఇక్కడ కవర్ చేయబడదు" (ఐఈఈఈ 754 ప్రమాణానికి రీడర్‌ను తెలివిగా సూచిస్తూ). ఇక్కడ ఏ రకమైన లోపాలు ఉద్దేశించబడ్డాయి? వాటిని క్రమపద్ధతిలో చర్చిద్దాం, నేను మళ్లీ పెన్ను ఎందుకు తీసుకున్నానో త్వరలో స్పష్టమవుతుంది.

ఉదాహరణకు ఒక సాధారణ అభ్యర్థనను తీసుకుందాం:

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

ఫలితంగా, మేము ప్రత్యేకంగా ఏమీ చూడలేము - మేము ఊహించిన 0.1ని పొందుతాము. కానీ ఇప్పుడు దానిని 0.1తో పోల్చండి:

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

సమానము కాదు! ఏమి అద్భుతాలు! కానీ మరింత, మరింత. ఎవరో చెబుతారు, REAL భిన్నాలతో చెడుగా ప్రవర్తిస్తుందని నాకు తెలుసు, కాబట్టి నేను అక్కడ పూర్ణ సంఖ్యలను నమోదు చేస్తాను మరియు ప్రతిదీ ఖచ్చితంగా వారితో బాగానే ఉంటుంది. సరే, 123 సంఖ్యను రియల్‌కి ప్రసారం చేద్దాం:

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

మరియు అది మరో 3 అని తేలింది! అంతే, డేటాబేస్ చివరికి ఎలా లెక్కించాలో మర్చిపోయింది! లేక మనం ఏదో అపార్థం చేసుకుంటున్నామా? దాన్ని గుర్తించండి.

మొదట, పదార్థాన్ని గుర్తుంచుకోండి. మీకు తెలిసినట్లుగా, ఏదైనా దశాంశ సంఖ్యను పది శక్తులుగా విస్తరించవచ్చు. కాబట్టి, 123.456 సంఖ్య 1*102 + 2*101 + 3*100 + 4*10-1 + 5*10-2 + ​​6*10-3కి సమానంగా ఉంటుంది. కానీ కంప్యూటర్ బైనరీ రూపంలో సంఖ్యలతో పనిచేస్తుంది, కాబట్టి అవి రెండు శక్తులలో విస్తరణ రూపంలో సూచించబడాలి. కాబట్టి, బైనరీలో 5.625 సంఖ్య 101.101గా సూచించబడుతుంది మరియు 1*22 + 0*21 + 1*20 + 1*2-1 + 0*2-2 + 1*2-3కి సమానంగా ఉంటుంది. మరియు రెండు యొక్క సానుకూల శక్తులు ఎల్లప్పుడూ మొత్తం దశాంశ సంఖ్యలను (1, 2, 4, 8, 16, మొదలైనవి) ఇస్తే, ప్రతికూల వాటితో ప్రతిదీ మరింత క్లిష్టంగా ఉంటుంది (0.5, 0.25, 0.125, 0,0625, మొదలైనవి). సమస్య ఏమిటంటే ప్రతి దశాంశం పరిమిత బైనరీ భిన్నం వలె సూచించబడదు. కాబట్టి, బైనరీ భిన్నం రూపంలో మన అపఖ్యాతి పాలైన 0.1 ఆవర్తన విలువ 0.0(0011)గా కనిపిస్తుంది. తత్ఫలితంగా, కంప్యూటర్ మెమరీలో ఈ సంఖ్య యొక్క చివరి విలువ బిట్ డెప్త్‌పై ఆధారపడి మారుతుంది.

కంప్యూటర్ మెమరీలో వాస్తవ సంఖ్యలు ఎలా నిల్వ చేయబడతాయో గుర్తుంచుకోవలసిన సమయం ఇది. సాధారణంగా చెప్పాలంటే, వాస్తవ సంఖ్య మూడు ప్రధాన భాగాలను కలిగి ఉంటుంది - గుర్తు, మాంటిస్సా మరియు ఘాతాంకం. గుర్తు ప్లస్ లేదా మైనస్ కావచ్చు, కాబట్టి దాని కోసం ఒక బిట్ కేటాయించబడుతుంది. కానీ మాంటిస్సా మరియు ఘాతాంకం యొక్క బిట్‌ల సంఖ్య నిజమైన రకం ద్వారా నిర్ణయించబడుతుంది. కాబట్టి, నిజమైన రకం కోసం, మాంటిస్సా యొక్క పొడవు 23 బిట్‌లు (1కి సమానమైన ఒక బిట్ మాంటిస్సా ప్రారంభానికి పరోక్షంగా జోడించబడుతుంది మరియు ఫలితం 24), మరియు ఘాతాంకం 8 బిట్‌లు. మొత్తం 32 బిట్‌లు లేదా 4 బైట్లు. మరియు DOUBLE PRECISION రకం కోసం, మాంటిస్సా యొక్క పొడవు 52 బిట్‌లు మరియు ఘాతాంకం 11 బిట్‌లు, మొత్తం 64 బిట్‌లు లేదా 8 బైట్‌లు. PostgreSQL ఫ్లోటింగ్ పాయింట్ నంబర్‌లకు అధిక ఖచ్చితత్వానికి మద్దతు ఇవ్వదు.

మన దశాంశ సంఖ్య 0.1ని నిజమైన మరియు డబుల్ ఖచ్చితత్వ రకాలుగా ప్యాక్ చేద్దాం. ఘాతాంకం యొక్క సంకేతం మరియు విలువ ఒకే విధంగా ఉన్నందున, మేము మాంటిస్సాపై దృష్టి పెడతాము (ఘాతాంకం యొక్క విలువలు మరియు సున్నా వాస్తవ విలువలను నిల్వ చేసే స్పష్టమైన లక్షణాలను నేను ఉద్దేశపూర్వకంగా విస్మరిస్తున్నాను, ఎందుకంటే అవి అవగాహనను క్లిష్టతరం చేస్తాయి మరియు సారాంశం నుండి దృష్టి మరల్చుతాయి. సమస్య యొక్క, ఆసక్తి ఉంటే, IEEE 754 ప్రమాణాన్ని చూడండి). మనం ఏమి పొందుతాము? టాప్ లైన్‌లో నేను రియల్ టైప్ కోసం “మాంటిస్సా” ఇస్తాను (చివరి బిట్‌ని 1 ద్వారా సమీప సూచించదగిన సంఖ్యకు చుట్టుముట్టడాన్ని పరిగణనలోకి తీసుకుంటే, లేకుంటే అది 0.099999 అవుతుంది...), మరియు బాటమ్ లైన్‌లో - కోసం DOUBLE PRECISION రకం:

0.000110011001100110011001101
0.00011001100110011001100110011001100110011001100110011001

సహజంగానే ఇవి రెండు పూర్తిగా భిన్నమైన సంఖ్యలు! అందువల్ల, పోల్చినప్పుడు, మొదటి సంఖ్య సున్నాలతో ప్యాడ్ చేయబడుతుంది మరియు అందువల్ల, రెండవదాని కంటే ఎక్కువగా ఉంటుంది (ఖాతా రౌండింగ్‌ను పరిగణనలోకి తీసుకుంటే - బోల్డ్‌లో గుర్తించబడినది). ఇది మా ఉదాహరణల నుండి అస్పష్టతను వివరిస్తుంది. రెండవ ఉదాహరణలో, స్పష్టంగా పేర్కొన్న సంఖ్య 0.1 డబుల్ PRECISION రకానికి ప్రసారం చేయబడుతుంది, ఆపై అనేక వాస్తవ రకంతో పోల్చబడుతుంది. రెండూ ఒకే రకానికి తగ్గించబడ్డాయి మరియు మనం పైన చూసేది ఖచ్చితంగా ఉంది. ప్రశ్నను సవరిద్దాం, తద్వారా ప్రతిదీ సరిగ్గా జరుగుతుంది:

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

వాస్తవానికి, 0.1 సంఖ్యను నిజమైన మరియు డబుల్ ఖచ్చితత్వానికి రెట్టింపు తగ్గించడం ద్వారా, మేము చిక్కుకు సమాధానాన్ని పొందుతాము:

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

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

ఇది పైన ఉన్న మూడవ ఉదాహరణను కూడా వివరిస్తుంది. 123 సంఖ్య చాలా సులభం మాంటిస్సాను 24 బిట్‌లుగా అమర్చడం అసాధ్యం (23 స్పష్టమైన + 1 సూచించబడింది). 24 బిట్‌లకు సరిపోయే గరిష్ట పూర్ణాంకం 224-1 = 16. కాబట్టి, మా సంఖ్య 777 సమీప సూచించదగిన 215కి గుండ్రంగా ఉంటుంది. రకాన్ని రెట్టింపు ఖచ్చితత్వానికి మార్చడం ద్వారా, మేము ఇకపై ఈ దృశ్యాన్ని చూడలేము:

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

అంతే. అద్భుతాలు లేవని తేలింది. కానీ వివరించిన ప్రతిదీ మీకు నిజంగా నిజమైన రకం ఎంత అవసరమో ఆలోచించడానికి మంచి కారణం. బహుశా దాని ఉపయోగం యొక్క అతిపెద్ద ప్రయోజనం ఖచ్చితత్వం యొక్క తెలిసిన నష్టంతో గణనల వేగం. కానీ ఇది ఈ రకమైన తరచుగా ఉపయోగించడాన్ని సమర్థించే సార్వత్రిక దృశ్యం అవుతుందా? అనుకోవద్దు.

మూలం: www.habr.com

ఒక వ్యాఖ్యను జోడించండి