အမျိုသအစာသမျာသ၏ အစစ်အမဟန်မဟုတ်သော အင်္ဂါရပ်မျာသ သို့မဟုတ် REAL ကို သတိထာသပါ။

ထုတ်ဝေပဌီသနောက် ဆောင်သပါသမျာသ PostgreSQL တလင် စာရိုက်ခဌင်သ၏အင်္ဂါရပ်မျာသနဟင့် ပတ်သက်၍ ပထမဆုံသမဟတ်ချက်မဟာ ကိန်သဂဏန်သအစစ်အမဟန်မျာသနဟင့် လုပ်ဆောင်ရသည့်အခက်အခဲမျာသအကဌောင်သဖဌစ်သည်။ REAL အမျိုသအစာသကို မည်မျဟအသုံသပဌုလေ့ရဟိသည်ကို သိရန် ကျလန်ုပ်အတလက်ရရဟိနိုင်သော SQL queries ၏ကုဒ်ကို အမဌန်ကဌည့်ရန် ဆုံသဖဌတ်ခဲ့သည်။ ၎င်သကိုမကဌာခဏအသုံသပဌုကဌောင်သတလေ့ရပဌီသ developer မျာသသည်၎င်သ၏နောက်ကလယ်ရဟိအန္တရာယ်မျာသကိုအမဌဲတမ်သနာသမလည်ပါ။ ကလန်ပဌူတာမဟတ်ဉာဏ်တလင် ကိန်သဂဏန်သအစစ်အမဟန်မျာသကို သိမ်သဆည်သခဌင်သနဟင့် ၎င်သတို့နဟင့် လုပ်ဆောင်ခဌင်သဆိုင်ရာ အင်္ဂါရပ်မျာသအကဌောင်သ အင်တာနက်နဟင့် Habré တလင် ကောင်သမလန်သော ဆောင်သပါသမျာသစလာ အမျာသအပဌာသရဟိသော်လည်သ ၎င်သသည် ၎င်သကို အသုံသပဌုထာသသည်။ ထို့ကဌောင့်၊ ကဆောင်သပါသတလင် PostgreSQL တလင်ထိုကဲ့သို့သောအင်္ဂါရပ်မျာသကိုအသုံသပဌုရန်ကဌိုသစာသမည်ဖဌစ်ပဌီသ၊ ၎င်သတို့နဟင့်ဆက်စပ်နေသောပဌဿနာမျာသကို SQL query developer မျာသရဟောင်ရဟာသရန်ပိုမိုလလယ်ကူစေရန်အတလက်၎င်သတို့နဟင့်ဆက်စပ်နေသောပဌဿနာမျာသကိုအမဌန်ကဌည့်ရဟုရန်ကဌိုသစာသပါမည်။

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 သည် အပိုင်သကိန်သမျာသဖဌင့် ဆိုသရလာသစလာ ပဌုမူသည်ကို ကျလန်ုပ်သိသည်၊ ထို့ကဌောင့် ကျလန်ုပ်သည် ထိုနေရာတလင် ဂဏန်သမျာသကို လုံသထည့်လိုက်မည်ဖဌစ်ပဌီသ၊ အရာအာသလုံသသည် ၎င်သတို့နဟင့် သေချာပေါက် အဆင်ပဌေလိမ့်မည်ဖဌစ်ကဌောင်သ တစ်စုံတစ်ယောက်က ပဌောလိမ့်မည်။ OK၊ နံပါတ် 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 နဟင့် ညီမျဟပါမည်။ သို့သော် ကလန်ပျူတာသည် ကိန်သဂဏန်သမျာသဖဌင့် binary ပုံစံဖဌင့် လုပ်ဆောင်သောကဌောင့် ၎င်သတို့အာသ စလမ်သအာသနဟစ်ခု၏ ချဲ့ထလင်မဟုပုံစံဖဌင့် ကိုယ်စာသပဌုရမည်ဖဌစ်သည်။ ထို့ကဌောင့်၊ ဒလိကိန်သတလင် 5.625 ကို 101.101 အဖဌစ် ကိုယ်စာသပဌုပဌီသ 1*22 + 0*21 + 1*20 + 1*2-1 + 0*2-2 + 1*2-3 နဟင့် ညီမျဟပါမည်။ အကယ်၍ နဟစ်ခု၏ အပဌုသဘောဆောင်သော ပါဝါမျာသသည် ဒဿမဂဏန်သမျာသ (၁၊ ၂၊ ၄၊ ၈၊ ၁၆ စသည်) ကို အမဌဲပေသမည်ဆိုပါက၊ အနဟုတ်လက္ခဏာမျာသဖဌင့် အရာအာသလုံသသည် ပိုမိုရဟုပ်ထလေသသည် (1၊ 2၊ 4၊ 8 စသည်)။ ပဌဿနာက အဲဒါ ဒဿမတစ်ခုစီတိုင်သကို ကန့်သတ်ဒလိအပိုင်သအစအဖဌစ် ကိုယ်စာသပဌု၍မရနိုင်ပါ။. ထို့ကဌောင့်၊ ကျလန်ုပ်တို့၏ နာမည်ဆိုသဖဌင့်ကျော်ကဌာသသော 0.1 သည် ဒလိအပိုင်သအစပုံစံဖဌင့် အချိန်အပိုင်သအခဌာသတန်ဖိုသ 0.0(0011) အဖဌစ်ပေါ်လာသည်။ ထို့ကဌောင့်၊ ကလန်ပျူတာမဟတ်ဉာဏ်ရဟိ ကနံပါတ်၏နောက်ဆုံသတန်ဖိုသသည် ဘစ်အတိမ်အနက်ပေါ် မူတည်၍ ကလဲပဌာသလိမ့်မည်။

ယခုအချိန်သည် ကလန်ပျူတာမဟတ်ဉာဏ်တလင် ဂဏန်သအစစ်အမဟန်မျာသကို မည်ကဲ့သို့ သိမ်သဆည်သထာသသည်ကို မဟတ်သာသရမည့်အချိန်ဖဌစ်သည်။ ယေဘူယျအာသဖဌင့်ပဌောရလျဟင်၊ အစစ်အမဟန်ကိန်သဂဏန်သတလင် နိမိတ်လက္ခဏာ၊ mantissa နဟင့် ထပ်ကိန်သသုံသမျိုသပါဝင်သည်။ နိမိတ်သည် အပေါင်သ သို့မဟုတ် အနုတ် ဖဌစ်နိုင်သည်၊ ထို့ကဌောင့် ၎င်သအတလက် တစ်ဘစ်ကို ခလဲဝေပေသသည်။ သို့သော် mantissa ၏ bits နဟင့် exponent အရေအတလက်ကို real type ဖဌင့်ဆုံသဖဌတ်သည်။ ထို့ကဌောင့်၊ အစစ်အမဟန်အမျိုသအစာသအတလက်၊ mantissa ၏အရဟည်မဟာ 23 bits (1 နဟင့်ညီမျဟသော bit ကို mantissa ၏အစတလင် သလယ်ဝိုက်စလာထည့်ထာသပဌီသ ရလဒ်မဟာ 24) ဖဌစ်ပဌီသ ထပ်ကိန်သသည် 8 bits ဖဌစ်သည်။ စုစုပေါင်သသည် 32 bits သို့မဟုတ် 4 bytes ဖဌစ်သည်။ နဟစ်ဆတိကျသောအမျိုသအစာသအတလက်၊ mantissa ၏အရဟည်သည် 52 bits ဖဌစ်မည်ဖဌစ်ပဌီသ ထပ်ကိန်သသည် 11 bits ဖဌစ်မည်ဖဌစ်ပဌီသ စုစုပေါင်သ 64 bits သို့မဟုတ် 8 bytes ဖဌစ်သည်။ PostgreSQL သည် Floating Point နံပါတ်မျာသအတလက် ပိုမိုတိကျမဟုကို မပံ့ပိုသပါ။

ကျလန်ုပ်တို့၏ ဒဿမ နံပါတ် 0.1 ကို အစစ်အမဟန်နဟင့် နဟစ်ဆတိကျမဟု အမျိုသအစာသမျာသအဖဌစ် ထုပ်ပိုသကဌပါစို့။ ထပ်ကိန်သ၏နိမိတ်လက္ခဏာနဟင့်တန်ဖိုသတို့သည် တူညီသောကဌောင့်၊ ကျလန်ုပ်တို့သည် mantissa ကိုအာရုံစိုက်ပါမည် (ထပ်ကိန်သ၏တန်ဖိုသမျာသနဟင့် သုညအစစ်အမဟန်တန်ဖိုသမျာသကို သိမ်သဆည်သခဌင်သ၏တန်ဖိုသမျာသကို တမင်တကာ ချန်လဟပ်ထာသပါသည်၊ ၎င်သတို့သည် နာသလည်မဟုကို ရဟုပ်ထလေသစေပဌီသ အနဟစ်သာရမဟ အာရုံလလဟဲသလာသသောကဌောင့်၊ ပဌဿနာကို စိတ်ဝင်စာသပါက IEEE 754 စံနဟုန်သကို ကဌည့်ပါ။) ငါတို့ဘာရမဟာလဲ? အပေါ်ဆုံသစာကဌောင်သတလင် REAL အမျိုသအစာသအတလက် "mantissa" ကို ပေသမည် (နောက်ဆုံသဘစ်၏ အနီသဆုံသကိုယ်စာသပဌုနံပါတ်သို့ 1 ဖဌင့် အဝိုင်သခဌင်သကို ထည့်သလင်သတလက်ချက်ခဌင်သ၊ မဟုတ်ပါက 0.099999...) နဟင့် အောက်ခဌေလိုင်သတလင် - for နဟစ်ဆတိကျမဟု အမျိုသအစာသ-

0.000110011001100110011001101
0.00011001100110011001100110011001100110011001100110011001

ထင်ရဟာသသည်မဟာ ကဂဏန်သနဟစ်လုံသသည် လုံသဝကလဲပဌာသပါသည်။ ထို့ကဌောင့် နဟိုင်သယဟဥ်သောအခါ ပထမနံပါတ်ကို သုညဖဌင့် ဖုံသအုပ်ထာသမည်ဖဌစ်ပဌီသ၊ ထို့ကဌောင့်၊ ဒုတိယဂဏန်သထက် ကဌီသမည် (အဝိုင်သပုံ - စာလုံသကဌီသဖဌင့် အမဟတ်အသာသပဌုထာသသည်) ကို ထည့်သလင်သစဉ်သစာသပါ။ ယင်သက ကျလန်ုပ်တို့၏ ဥပမာမျာသမဟ မရဟင်သလင်သမဟုကို ရဟင်သပဌသည်။ ဒုတိယဥပမာတလင်၊ ပဌတ်သာသစလာသတ်မဟတ်ထာသသောနံပါတ် 0.1 ကို DOUBLE PRECISION အမျိုသအစာသသို့ ကာစ်လိုက်ပဌီသ REAL အမျိုသအစာသ၏ အရေအတလက်နဟင့် နဟိုင်သယဟဉ်ပါသည်။ နဟစ်မျိုသလုံသကို အမျိုသအစာသတူသို့ လျဟော့ချထာသပဌီသ အထက်တလင် မဌင်တလေ့ရသည့် အတိအကျရဟိသည်။ အာသလုံသအဆင်ပဌေစေရန် query ကို ပဌင်ဆင်ကဌပါစို့။

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

အမဟန်ပင်၊ နံပါတ် 0.1 ကို အစစ်အမဟန်နဟင့် နဟစ်ဆတိကျမဟုသို့ နဟစ်ဆလျဟော့ချခဌင်သဖဌင့်၊ ကျလန်ုပ်တို့သည် ပဟေဠိအတလက် အဖဌေကို ရရဟိသည်-

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

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

၎င်သသည် အထက်ဖော်ပဌပါ တတိယဥပမာကိုလည်သ ရဟင်သပဌထာသသည်။ နံပါတ် 123 သည် ရိုသရဟင်သပါသည်။ mantissa ကို 24 bits နဲ့ ညဟိဖို့ မဖဌစ်နိုင်ပါဘူသ။ (၂၃ ပဌတ်သာသ + ၁ အဓိပ္ပာယ်သက်ရောက်သည်)။ 23 bits တလင် အံဝင်ခလင်ကျနိုင်သော အမဌင့်ဆုံသ ကိန်သပဌည့်သည် 1-24 = 224 ဖဌစ်သည်။ ထို့ကဌောင့်၊ ကျလန်ုပ်တို့၏ နံပါတ် 1 ကို အနီသဆုံသ ကိုယ်စာသပဌုနိုင်သော 16 သို့ ဝိုင်သထာသသည်။ အမျိုသအစာသကို နဟစ်ဆ ကဌိုတင်ပဌင်ဆင်ခဌင်သဖဌင့်၊ ကျလန်ုပ်တို့ မတလေ့ရတော့ပါ။

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

ဒါပါပဲ။ အံ့ဖလယ်အမဟုမျာသ မရဟိတော့သည်ကို တလေ့ရပါသည်။ သို့သော် ဖော်ပဌထာသသည့်အရာအာသလုံသသည် အစစ်အမဟန်အမျိုသအစာသကို သင်အမဟန်တကယ်လိုအပ်သည်နဟင့် ပတ်သက်၍ စဉ်သစာသရန် အကဌောင်သပဌချက်ကောင်သတစ်ခုဖဌစ်သည်။ ၎င်သ၏အသုံသပဌုမဟု၏အကဌီသမာသဆုံသအာသသာချက်မဟာ တိကျမဟုပျောက်ဆုံသခဌင်သနဟင့်အတူ တလက်ချက်မဟုမျာသ၏အမဌန်နဟုန်သဖဌစ်ကောင်သဖဌစ်နိုင်သည်။ သို့သော် ကအမျိုသအစာသကို မကဌာခဏအသုံသပဌုခဌင်သသည် တရာသမျဟတစေမည့် universal scenario ဖဌစ်မလာသ။ မထင်ပါနဟင့်။

source: www.habr.com

မဟတ်ချက် Add