Program ကုဒ်တွေနဲ့ သင်္ချာတွက်ချက်မှုပြုလုပ်တဲ့အခါ သတိထားရမယ့် အချက်အလက်တချို့ရှိပါတယ်။ အဲဒါတွေကို သတိမထားမိဘူးဆိုရင် ကိုယ့်ရဲ့တွက်ချက်မှုတွေဟာ အမှားအယွင်းတချို့ရဲ့ ရင်ဆိုင်ရတတ်ပါတယ်။ သာမန်အားဖြင့် သင်္ချာတွက်ချက်မှုတချို့ဟာ အမှားတချို့ကို ခွင့်ပြုလို့ရပေမယ့် နက္ခတ္တဗေဒလိုမျိုး သိပ္ပံနည်းကျတွက်ချက်ရတဲ့ ကိစ္စတွေမှာဆိုရင်တော့ ကိုယ့်ရဲ့တွက်ချက်မှုတွေဟာ တိကျနေဖို့လိုပါတယ်။ ကျနော်က PHP နဲ့ နက္ခတ္တဗေဒတွက်ချက်မှုတွေကို အများဆုံး လုပ်ဖြစ်နေတာဆိုတော့ PHP ရဲ့ သဘောတရားနဲ့ နှိုင်းယှဉ်ပြီး ဥပမာပေးပါ့မယ်။ ဆိုကြပါစို့ ... အောက်ပါကုဒ်ကို Run ကြည့်ရင် ဘာအဖြေရမယ်ထင်ပါသလဲ?
<?php
echo (0.1 + 0.2);
?>
အဖြေက 0.3 လို့ ရပါလိမ့်မယ်။ ဒီတော့ ကျနော်တို့က အဲဒါကို အဖြေမှန်ပဲလို့ ရုတ်တရက် ယုံကြည်သွားတတ်ပါတယ်။ တကယ်တော့ ဒါဟာ အဖြေမှန်တစ်ခုမဟုတ်ပါဘူး။ အဖြေမှန်လို့ ထင်ရအောင် PHP ရဲ့ echo() က ကျနော်တို့ကို မျက်လှည့်ပြပြီး Auto-rounding နဲ့ အဖြေထုတ်ပေးလိုက်တာဖြစ်ပါတယ်။ ကျနော်ဒီအတိုင်းပြောနေရင် မျက်စိလည်သွားနိုင်တဲ့အတွက် ကုဒ်သက်သေလေးနဲ့ ရှင်းပြပါမယ်။ သင်္ချာသဘောတရားအရ ... 0.3 -0.3 = 0 ဖြစ်ရမယ်လို့ ယူဆပြီး လက်တွေ့ တွက်ပြပါမယ်။
<?php
$sum = 0.1 + 0.2;
echo ($sum - 0.3);
?>
ဒီကုဒ်ရဲ့သဘောက ... 0.1 + 0.2 ကို ပေါင်းလိုက်မယ်။ ဒီတော့ ရလာတဲ့အဖြေကို $sum ထဲမှာ ယာယီထည့်သိမ်းလိုက်မယ်။ ဒီတော့ $sum တန်းဖိုက 0.3 ဖြစ်လာမယ်။ အဲဒီလိုဖြစ်လာမှာ ... 0.3 ကို ပြန်နုတ်ကြည့်မယ်။ 0.3-0.3 = 0 ဆိုတော့ အဖြေက သုညဖြစ်ရင် မှန်တယ်လို့ ယူဆရမှာပေါ့ ... လက်တွေ့ကုဒ်ကို Run ကြည့်လိုက်တဲ့အခါ အဖြေက ... 5.5511151231258E-17 ဖြစ်နေပါတယ်။ ဒီတော့ အဓိပ္ပါယ်က $sum ဖြစ်တဲ့ 0.1 + 0.2 ရဲ့ ပေါင်းခြင်းဟာ 0.3 ဖြစ်တယ်ဆိုတာ မမှန်ဘူးဆိုတဲ့ သက်သေပါပဲ။ ဒီတော့ မိတ်ဆွေက ဒါဆို ... PHP က 0.1 + 0.2 ပေါင်းခြင်းရလဒ်ကို တကယ်ဘယ်လိုတွက်ချက်ပေးသလဲ။ အဲဒီရလဒ်အမှန်က ဘာလဲဆိုပြီးတော့ သိချင်လိမ့်မယ်။ PHP က တကယ်တွက်ချက်ပေးတဲ့ သင်္ချာကိန်းအမှန်ကို သိချင်ရင် ကြည့်နိုင်တဲ့ နည်းလမ်း ၂ ခုရှိပါတယ်။ ပထမနည်းလမ်းက ... var_dump() သုံးကြည့်တဲ့နည်းပါ။ အောက်ပါကုဒ်ကို Run ကြည့်ပါ။
<?php
var_dump(0.1 + 0.2);
?>
အဖြေကို float(0.30000000000000004) လို့ ထုတ်ပြပါလိမ့်မယ်။ သက်ဆိုင်ရာ Data Type နဲ့ အဲဒီကိန်းရဲ့ ရလဒ်အစစ်အမှန်တန်ဖိုးဖြစ်ပါတယ်။ နောက်တနည်းနဲ့လည်း လုပ်လို့ရပါသေးတယ်။ အောက်ပါကုဒ်ကို Run ကြည့်ပါ။
<?php
ini_set('serialize_precision', '-1'); // PHP 7.1+ အတွက် တကယ့် RAM ထဲက အတိအကျဆုံး Float ကို ပြပေးမည့် Setting
ini_set('precision', '25');
echo (0.1 + 0.2);
?>
PHP ကုဒ်တွေကို precision = 14 အဖြစ် Default ထားကြပါတယ်။ ဒါက echo၊ print ဒါမှမဟုတ် String ပြောင်းတဲ့အခါ float ဂဏန်းကို စုစုပေါင်း ဂဏန်းအလုံးရေ (Significant Digits) ၁၄ လုံး အထိပဲ အနီးစပ်ဆုံး Round လုပ်ပြီး ပြပေးပါတယ်။ (ဒသမနောက်ပိုင်း ၁၄ လုံး မဟုတ်ပါဘူး၊ ရှေ့ဂဏန်းရော နောက်ဂဏန်းရော စုစုပေါင်း ၁၄ လုံးကို ဆိုလိုတာပါ။) အခု ကျနော်က ini_set('precision', '25'); နဲ့ ၂၅ လုံးထိပြအောင် ရေးလိုက်ပါတယ်။ တန်ဖိုးအမှန်ကို သိစေချင်လို့ပါ။ ini_set('serialize_precision', '-1'); ဆိုတာကတော့ json_encode() နဲ့ serialize() လုပ်တဲ့အခါ ဂဏန်းအစစ်ကို ပြန်ပြောင်းယူလို့ရမယ့် အတိုဆုံး တိကျတဲ့ ဂဏန်းအရေအတွက်ကို အလိုအလျောက် ရွေးပေးပါတယ်။ (PHP 7.0 နဲ့ အောက်ပိုင်းတွေမှာတော့ Default က 17 ဖြစ်ပါတယ်။) PHP 7.1 နဲ့ အထက်မှာတော့ -1 က Default ပါပဲ။ ဒီတော့ ကုဒ်ကို Run လိုက်တဲ့အခါ အဖြေက 0.300000000000000044408921 လို့ဖော်ပြပါတယ်။ ဒါကို ကြည့်ရင် echo (0.1 + 0.2); လို့ ရေးတတ်ရုံနဲ့ သင်္ချာတန်ဖိုး အမှန်မဟုတ်သေးဘူးဆိုတာကို ယုံကြည်လောက်ပြီထင်ပါတယ်။ အခုကျနော်ပြောပြခဲ့တာက မြင်သာစေဖို့နဲ့ လွယ်ကူစေဖို့ ခပ်လွယ်လွယ် လက်တွေ့ဥပမာပြခဲ့တာဖြစ်ပါတယ်။ ဒီလိုအချက်ကို ဂရုမစိုက်မိတဲ့အတွက် လက်တွေ့ နက္ခတ္တဗေဒပညာမှာ အယူအဆမှားယွင်းတတ်ပုံကို အထက်က ဥပမာလေးနဲ့ အနီးစပ်ဆုံးတူအောင် ကျနော် တစ်ခုလုပ်ပြပါဦးမယ်။ ဂြိုဟ်တစ်လုံးနဲ့ ဂြိုဟ်တစ်လုံးဟာ Trine 120° အမြင်ရှိသလားဆိုတာ စစ်ကြည့်ချင်တယ်ဆိုပါစို့။ ဥပမာအဖြစ် ... တနင်္ဂနွေဂြိုဟ်ဟာ 145.3 မှာရပ်တည်နေမယ်။ တနင်္လာဂြိုဟ်ကတော့ 25.3 မှာ ရပ်တည်နေမယ်။ ဒါဆိုရင် ... သင်္ချာသဘောအရ ... 145.3 - 25.3 = 120 အတိဖြစ်လို့ Trine အမြင်ရှိတယ်လို့ သိနိုင်ပါတယ်။ ဒါကို Program ကုဒ်ရေးတဲ့အခါ အောက်ပါအတိုင်း ရေးနိုင်ပါတယ်။
<?php
$sun = 145.3;
$moon = 25.3;
$diff = $sun - $moon;
echo($diff);
echo "<br>";
var_dump($diff == 120.0);
echo "<br>";
var_dump($diff);
?>
ဒီကုဒ်အရ ... $diff တန်ဖိုးဟာ ကျနော်တို့ လိုချင်တဲ့ 120 အဖြေဖြစ်ကြောင်းကို echo($diff); အရ မြင်တွေ့နိုင်ပါတယ်။ ဒါပေမယ့် တကယ်ရော ဟုတ်ရဲ့လားဆိုပြီး var_dump($diff == 120.0); နဲ့ စစ်ဆေးလိုက်တဲ့အခါ အဖြေက false ( မဟုတ်ဘူးလို့) အဖြေထွက်လာပါတယ်။ ဒါနဲ့ အဖြေအစစ်က ဘာထွက်နေလို့လဲဆိုပြီး ခပ်လွယ်လွယ်ပဲ var_dump($diff); နဲ့ စစ်ဆေးလိုက်တဲ့အခါ အဖြေက float(120.00000000000001) လို့ပြနေတာကို တွေ့ရပါတယ်။ အဲဒါဟာ ကျနော်တို့ မမြင်လိုက်ရတဲ့ ဒသကိန်းအသေးစားလေးတစ်ခုပါပဲ ... တကယ်တော့ ဒါတွေဟာ သင်္ချာပညာအရ ခွင့်ပြုနိုင်လောက်တဲ့ အမှားတွေလို့ ပြောလို့ရပေမယ့် နှစ်ပေါင်းသောင်းချီပြီး တိတိကျကျတွက်ချက်မှုတွေ ပြုလုပ်ရမယ့် နက္ခတ္တတွက်ရိုးတွေကို တွက်ချက်တဲ့အခါ အဲဒီ အကြွင်းအကျန်ဒသမလေးတွေဟာ တဖြေးဖြေးစုပုံလာပြီး သင်္ချာတွက်ချက်မှုကို များစွာ ထိခိုက်လာနိုင်ပါတယ်။ ဒါကြောင့် ကျနော် AstroTTS ဆိုတဲ့ နက္ခတ်တွက်ရိုး Library ကို ရေးသားတဲ့နေရာမှာ bcmath ကို အခြေခံထားတဲ့ AstroMath ဆိုတဲ့ ကိုယ်ပိုင် Library တစ်ခုကို ကြားခံပြီး တွက်ချက်ထားပါတယ်။ ဒီတော့ ... အဲဒီ ဒသမအကြွင်းအကျန်အမှားအယွင်းတွေကို ကျနော့်ရဲ့ AstroMath က ဖြေရှင်းပေးထားပြီးသားဖြစ်လို့ နှစ်သောင်းချီတွက်ပေမယ့်လည်း တိကျတဲ့ အဖြေမှန်ကိုသာ ထုတ်ပေးမှာဖြစ်ပါတယ်။ ကဲ ... ဒီတော့ Program တွေရေးတဲ့အခါ ဘယ်လိုလှည့်ကွက်လေးတွေရှိမယ်။ အထူးသဖြင့် PHP နဲ့ ကုဒ်ရေးတဲ့အခါ ဘယ်လိုလှည့်ကွက်တွေရှိနေမယ်ဆိုတာကို အကြမ်းအားဖြင့် ပညာရလောက်ပြီထင်ပါတယ်။ ဥပမာပေးစရာတွေ အများကြီးရှိပေမယ့် ရှည်ရှည်ဝေးဝေးတွေပြောပြနေရင် အရမ်းကြာနိုင်တာကြောင့် အလွယ်ဆုံးသဘောတရားတွေနဲ့သာ ရှင်းပြပေးလိုက်ပါတယ်။ အဆင်ပြေမယ်လို့ မျှော်လင့်ပါတယ်။

0 Comments