حقيقي قسمن جون غير حقيقي خاصيتون، يا REAL سان محتاط رھو

اشاعت کان پوء مضمون PostgreSQL ۾ ٽائپنگ جي خاصيتن بابت، پهريون تبصرو حقيقي انگن سان ڪم ڪرڻ جي مشڪلاتن بابت هو. مون فيصلو ڪيو ته مون وٽ موجود SQL سوالن جي ڪوڊ تي هڪ تڪڙو نظر وجهڻ لاءِ اهو ڏسڻ لاءِ ته اهي ڪيترا ڀيرا REAL قسم استعمال ڪندا آهن. اهو ظاهر ٿئي ٿو ته اهو اڪثر استعمال ڪيو ويندو آهي، ۽ ڊولپر هميشه ان جي پويان خطرن کي نه سمجهي. ۽ هن حقيقت جي باوجود ته انٽرنيٽ تي ۽ Habré تي ڪمپيوٽر جي ميموري ۾ حقيقي نمبرن کي محفوظ ڪرڻ ۽ انهن سان ڪم ڪرڻ جي خاصيتن بابت ڪافي سٺا مضمون آهن. تنهن ڪري، هن آرٽيڪل ۾ مان ڪوشش ڪندس ته اهڙين خاصيتن کي PostgreSQL تي لاڳو ڪرڻ جي، ۽ انهن سان لاڳاپيل مشڪلاتن تي تڪڙو جائزو وٺڻ جي ڪوشش ڪندس، ته جيئن SQL سوال ڊولپرز کي انهن کان بچڻ آسان بڻائي سگهجي.

PostgreSQL دستاويز مختصر طور تي بيان ڪري ٿو: "اهڙين غلطين جو انتظام ۽ انهن جي پروپيگيشن دوران حساب ڪتاب رياضي ۽ ڪمپيوٽر سائنس جي پوري شاخ جو موضوع آهي، ۽ هتي ڍڪيل نه آهي" (جڏهن ته عقلمنديء سان پڙهندڙ کي IEEE 754 معيار ڏانهن اشارو ڪيو ويو آهي). هتي ڪهڙي قسم جي غلطين جو مطلب آهي؟ اچو ته انهن تي ترتيب سان بحث ڪريون، پوءِ جلد ئي واضح ٿي ويندو ته مون ٻيهر قلم ڇو کنيو.

اچو ته مثال طور هڪ سادي درخواست وٺون:

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

نتيجي طور، اسان ڪجھ خاص نه ڏسندا سين - اسان کي متوقع 0.1 حاصل ڪنداسين. پر هاڻي اچو ته ان جو مقابلو 0.1 سان ڪريون:

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

برابر ناهي! ڪهڙا معجزا! پر اڳتي، وڌيڪ. ڪو چوندو، مون کي خبر آهي ته REAL جزن سان خراب رويو رکي ٿو، تنهن ڪري مان اتي پورو انگ داخل ڪندس، ۽ يقيناً انهن سان سڀ ڪجهه ٺيڪ ٿي ويندو. ٺيڪ، اچو ته نمبر 123 کي REAL ۾ اڇلون:

********* ЗАПРОС *********
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 بائيٽ. ۽ ڊبل PRECISION قسم لاءِ، مينٽيسا جي ڊگھائي 52 بِٽ هوندي، ۽ ايڪسپونٽ 11 بِٽ، ڪل 64 بِٽ، يا 8 بِٽَن لاءِ هوندو. PostgreSQL سچل پوائنٽ نمبرن لاءِ اعليٰ درستگي کي سپورٽ نٿو ڪري.

اچو ته اسان جي ڊيسيمل نمبر 0.1 کي REAL ۽ Double PRECISION ٻنهي قسمن ۾ ڀريون. جيئن ته exponent جي نشاني ۽ قدر هڪجهڙا آهن، تنهنڪري اسان مينٽيسا تي ڌيان ڏينداسين (مان عمدي طور تي ظاهر ڪندڙ جي قدرن کي محفوظ ڪرڻ جي غير واضح خصوصيتن کي ڇڏي ڏيان ٿو ۽ صفر حقيقي قدر، ڇاڪاڻ ته اهي سمجھڻ کي پيچيده ڪن ٿا ۽ جوهر کان پريشان ڪن ٿا. مسئلو جو، جيڪڏهن دلچسپي وٺندي، ڏسو IEEE 754 معيار). اسان کي ڇا حاصل ٿيندو؟ مٿين لڪير ۾ مان ڏيندس حقيقي قسم لاءِ ”مانٽيسا“ (جي حساب ۾ وٺندي آخري بٽ جي گول ڪرڻ کي 1 کان ويجھي نمايان انگ تائين، ٻي صورت ۾ اهو ٿيندو 0.099999...)، ۽ هيٺئين لڪير ۾ - لاءِ ڊبل 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 تائين گول ڪيو ويو آھي. قسم کي ڊبل PRECISION ۾ تبديل ڪرڻ سان، اسان ھاڻي ھي منظر نه ٿا ڏسون.

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

اهو ئي سڀ ڪجهه آهي. اهو ظاهر ٿئي ٿو ته ڪو معجزو نه آهي. پر بيان ڪيل هر شي هڪ سٺو سبب آهي انهي بابت سوچڻ لاءِ ته توهان کي حقيقي قسم جي ڪيتري ضرورت آهي. شايد ان جي استعمال جو سڀ کان وڏو فائدو اهو آهي ته حساب ڪتاب جي رفتار هڪ ڄاڻايل نقصان جي درستگي سان آهي. پر ڇا اهو هڪ آفاقي منظر هوندو جيڪو هن قسم جي بار بار استعمال کي جائز ثابت ڪندو؟ نه سوچيو.

جو ذريعو: www.habr.com

تبصرو شامل ڪريو