2015-06-29 9 views
5

में डबल-प्रकार डेटा (जियोलोकेशन) बचत मेरी MySQL डेटाबेस में दोगुना हो जाता है के रूप में मैं जियोलोकेशन डेटा भंडारण के लिये दो क्षेत्रों, परिभाषित किया गया है:अजीब मूल्य परिवर्तन जब डेटाबेस

`address_geo_latitude` float(10,6) NOT NULL, 
`address_geo_longitude` float(10,6) NOT NULL 

और मैं उपयोग कर रहा हूँ Yii2 के उपयोगकर्ता द्वारा पारित मूल्यों पर double सत्यापनकर्ता:

public function rules() 
{ 
    return [ 
     [['address_geo_latitude', 'address_geo_longitude'], 'double', 'min'=>0, 'max'=>360] 
    ]; 
} 

परीक्षण I'v के दौरान (हालांकि मेरे परीक्षण साबित हो सकता है, इस मुद्दे Yii2 प्रमाणकों के साथ कोई संबंध नहीं है कि लगता है) ई मनाया अजीब मूल्यों के परिवर्तन, यानी (?):

  • 359.90359.899994 (0,000006 अंतर) हो जाता है,
  • 359.80359.799988 हो जाता है (0,000012 अंतर),
  • 311.11311.109985 (0,000015 अंतर) हो जाता है,
  • 255.55255.550003 (-0,000003 अंतर) बन गया,
  • 205.205 हो जाता है 205.205002 (-0,000002 अंतर),
  • 105.105105.105003 (-0,000003 अंतर) हो जाता है।

लेकिन:

  • 359.899994359.899994 बनी हुई है,
  • 311.109985 रहता 311.109985,
  • 311 रहता 311,
  • 255 रहता 255,
  • 200 अवशेष 200,
  • 75.7575.75 बनी हुई है,
  • 11.1111.11 बनी हुई है।

मुझे क्या याद आ रही है? मैं इनके पीछे कोई पैटर्न या तर्क नहीं देख सकता।

क्या यह है, क्योंकि मेरे पास इस प्रकार के डेटा के लिए गलत MySQL फ़ील्ड घोषणा है? यदि हां, तो सही क्या है? कुछ अलग जवाब:

पता चलता है, कि float(10,6) उपयोग करते हुए, सबसे अच्छा विकल्प है यदि MySQL के spatial extensions का उपयोग नहीं।

print_r(Yii::$app->request->post()); //Correct! 
print_r($lab->address_geo_latitude); //Correct! 

if ($lab->load(Yii::$app->request->post(), 'Lab') && $lab->save()) { 
    print_r($lab->address_geo_latitude); //Correct! 

    $lab2 = $this->findModel($lab->id); 
    print_r($lab2->address_geo_latitude); //<-- HERE! Incorrect! 
} 

मेरा प्रश्न this one के विपरीत पर है: क्योंकि मूल्य जब तक डेटाबेस से फिर से पढ़ सही रहता है

मेरे परीक्षण, साबित हो सकता है, इस मुद्दे Yii2 प्रमाणकों के साथ कोई संबंध नहीं है कि लगता है। मेरी संख्या लाभ, हार नहीं, सटीकता! और केवल कुछ संख्याओं के लिए, हमेशा नहीं।

+0

* mysql * में फिर से सही होने के बाद मान सही हैं? – Tony

+0

@ टोनी क्षमा करें, मैं आपके प्रश्न को समझ नहीं पा रहा हूं, क्योंकि मैंने कभी दूसरी बचत के बारे में कुछ भी नहीं कहा, केवल दूसरे पढ़ने के बारे में (पुनः पढ़ा गया)। हां, 'address_geo_latitude' कॉलम में' 311.109985' मान को वास्तव में स्टोर/रखने के लिए '$ model-> save_) 'value_geo_latitude = 311.11' के रूप में सहेजा गया' $ model-> save()' मान के तुरंत बाद। – trejder

उत्तर

2

यह वाईआई के कारण नहीं होता है लेकिन बाइनरी सिस्टम पर फ़्लोटिंग-पॉइंट मान कैसे संग्रहीत किए जाते हैं।

आप MySQL documentation "फ्लोटिंग प्वाइंट मान के साथ कोई समस्या" में पढ़ सकते हैं के रूप में:

फ्लोटिंग-बिन्दु संख्या कभी कभी भ्रम की स्थिति पैदा कर रहे हैं, क्योंकि वे अनुमानित हैं और सटीक मान के रूप में जमा नहीं। SQL स्टेटमेंट में लिखे गए के रूप में फ़्लोटिंग-पॉइंट मान आंतरिक रूप से प्रतिनिधित्व किए गए मान जैसा नहीं हो सकता है। उदाहरण के साथ इस समस्या के लिए

Here you can find the great explanation। जैसा कि आप देख सकते हैं कि संख्याएं थोड़ी बड़ी हो सकती हैं, छोटी या बिल्कुल नहीं बदली जा सकती हैं लेकिन आपको हमेशा याद रखना होगा कि यह केवल एक अनुमान है।

gelocation डेटा के लिए आप सरल DECIMAL type उपयोग सुनिश्चित मूल्यों डेटाबेस में कोई बदलाव नहीं जमा हो जाती है बनाने या Spacial Data type की दुकान और क्वेरी डेटा कि एक ज्यामितीय अंतरिक्ष में परिभाषित वस्तुओं का प्रतिनिधित्व करता करने के लिए अनुकूलित का उपयोग कर सकते हैं।

+0

जैसा कि मैंने अपने प्रश्न में लिखा था (क्या मैंने किया?) गोलाकार या अनुमान मुझे ज्ञात है, लेकिन इसका इस मुद्दे से कोई लेना देना नहीं है। राउंडिंग प्रोग्रामिंग और गणित दोनों में, निकटतम संख्या की ओर हमेशा होती है। यह परिशुद्धता खोने के बारे में है, इसे प्राप्त नहीं कर रहा है। आप '105.105' को' 105.105003' में बदलकर कॉल नहीं कर सकते हैं क्योंकि यह एक गोल नहीं है और यह एक बेतुका और गणितीय रूप से गलत ऑपरेशन है। – trejder

+1

@trejder उत्तर में उल्लिखित mysql दस्तावेज का एक पुराना संस्करण https://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html का एक अच्छा उदाहरण है कि विभिन्न फ़्लोटिंग पॉइंट नंबर कैसे हो सकते हैं जब आप अधिक दशमलव स्थान जोड़ते हैं तो प्रतिनिधित्व किया जाता है, इसलिए * फ्लोट * के बजाय * दशमलव * का उपयोग करने का प्रयास करें, और – Tony

+0

@ बिज़ले के परिणामों की तुलना करें, क्या आप यहां इनमें से अधिकतर टिप्पणियों और शायद [इस उत्तर] को जोड़कर अपना जवाब दोबारा कर सकते हैं (http : //stackoverflow.com/a/163084/1469208)। आपने वास्तव में समस्या हल कर ली है! :> 'फ्लोट (10,6) 'से' दशमलव (9,6)' बदलना एक चमत्कार करें और कोई और मूल्य बदलना प्रकट नहीं होता है। एक बार जब आप इसे दोबारा शुरू करेंगे, तो मुझे आपका जवाब स्वीकार करने में खुशी होगी। – trejder

संबंधित मुद्दे