2017-03-23 10 views
18

यह कोई प्रश्न नहीं है क्योंकि यह अधिक जागरूक है। मैंने एक एप्लीकेशन अपडेट किया जो json_encode() का उपयोग PHP7.1.1 में करता है और मुझे कभी-कभी 17 अंकों का विस्तार करने के लिए फ्लोट्स बदलने के साथ कोई समस्या दिखाई दे रही थी। दस्तावेज़ीकरण के अनुसार, PHP 7.1.x ने डबल मानों को एन्कोड करते समय सटीकता के बजाय serialize_precision का उपयोग करना शुरू किया। मैं इसPHP7.1 json_encode() फ्लोट समस्या

472,185

का एक उदाहरण मूल्य की वजह से बाद कि मूल्य json_encode() माध्यम से चला गया

472,18500000000006

बनने के लिए अनुमान लगा रहा हूँ। मेरी खोज के बाद से, मैं वापस PHP 7.0.16 पर वापस आ गया है और अब मुझे json_encode() के साथ समस्या नहीं है। मैंने PHP 7.0.16 पर वापस लौटने से पहले PHP 7.1.2 को अपडेट करने का भी प्रयास किया।

इस प्रश्न के पीछे तर्क PHP - Floating Number Precision से निकलता है, हालांकि इसके लिए सभी कारण json_encode() में परिशुद्धता से serialize_precision उपयोग में परिवर्तन के कारण हैं।

अगर किसी को इस समस्या का समाधान पता है, तो मुझे तर्क/फिक्स पर सुनकर खुशी होगी। बहुआयामी सरणी से

अंश (पहले):

[staticYaxisInfo] => Array 
        (
         [17] => stdClass Object 
          (
           [variable_id] => 17 
           [static] => 1 
           [min] => 0 
           [max] => 472.185 
           [locked_static] => 1 
          ) 

        ) 

और json_encode() के माध्यम से जाने के बाद ...

"staticYaxisInfo": 
      { 
       "17": 
       { 
        "variable_id": "17", 
        "static": "1", 
        "min": 0, 
        "max": 472.18500000000006, 
        "locked_static": "1" 
       } 
      }, 
+1

'ini_set ('serialize_precision', 14); ini_set ('परिशुद्धता', 14); 'संभवतया इसे धारावाहिक बनाने के लिए उपयोग किया जाएगा, हालांकि यदि आप वास्तव में अपने फ्लोट पर एक विशिष्ट परिशुद्धता पर भरोसा करते हैं तो आप कुछ गलत कर रहे हैं। – apokryfos

+0

इसे 17 के रूप में डिफॉल्ट किया गया था, लेकिन मैंने इसे "बढ़ाया एल्गोरिदम" लेने के लिए -1 में बदल दिया। कोई पाँसा नहीं। – Gwi7d31

+1

* "अगर कोई इस समस्या के समाधान के बारे में जानता है" * - क्या समस्या है? मुझे यहां कोई समस्या नहीं दिखाई दे रही है। यदि आप PHP का उपयोग कर JSON को डीकोड करते हैं तो आप उस मान को वापस ले लेंगे जिसे आपने एन्कोड किया था। और यदि आप इसे एक अलग भाषा का उपयोग करके डीकोड करते हैं तो शायद आपको वही वैल्यू मिल जाए। किसी भी तरह से, यदि आप 12 अंकों के साथ मान मुद्रित करते हैं तो आप मूल ("सही") मान वापस लेते हैं। क्या आपको अपने आवेदन द्वारा उपयोग की जाने वाली फ्लोट के लिए 12 से अधिक दशमलव अंकों की सटीकता की आवश्यकता है? – axiac

उत्तर

26

यह मैं पागल थोड़ा के लिए चलाई जब तक मैं अंत में this bug जो आप की ओर इशारा करता पाया this RFC जो कहता है

वर्तमान में json_encode() ईजी (परिशुद्धता) का उपयोग करता है जो 14 पर सेट होता है। इसका मतलब है कि अधिकतर 14 अंकों का उपयोग संख्या (प्रिंटिंग) को प्रदर्शित करने के लिए किया जाता है। आईईईई 754 डबल उच्च परिशुद्धता का समर्थन करता है और serialize()/var_export() पीजी (serialize_precision) का उपयोग करता है जो 17 पर सेट होता है और अधिक सटीक होने के लिए डिफ़ॉल्ट होता है। चूंकि json_encode() ईजी (परिशुद्धता) का उपयोग करता है, json_encode() अंश भागों के निचले अंकों को हटा देता है और मूल मान को नष्ट कर देता है भले ही PHP की फ्लोट अधिक सटीक फ्लोट मान रख सके।

और (जोर मेरा)

यह आरएफसी एक नई सेटिंग ईजी (सटीक) पेश करने का प्रस्ताव है = - 1 और पीजी (serialize_precision) = - 1 zend_dtoa का उपयोग करता है() के मोड 0 जो फ्लोट नंबर राउंडिंग के लिए बेहतर एल्गोरिदम का उपयोग करता है (-1 0 मोड इंगित करने के लिए प्रयोग किया जाता है)

संक्षेप में, PHP 7.1 json_encode को नए और बेहतर परिशुद्धता इंजन का उपयोग करने का एक नया तरीका है। PHP में।आरं आप

serialize_precision = -1 

करने serialize_precision बदल आप इसे इस कमांड लाइन के साथ काम करता सत्यापित कर सकते हैं की जरूरत है

php -r '$price = ["price" => round("45.99", 2)]; echo json_encode($price);' 

आप

{"price":45.99} 
4

प्राप्त करना चाहिए एक प्लगइन डेवलपर मेरे पास नहीं है के रूप में सर्वर की php.ini सेटिंग्स तक सामान्य पहुंच। इसलिए, माचविटी के जवाब के आधार पर मैंने कोड का यह छोटा टुकड़ा लिखा है जिसे आप अपनी PHP स्क्रिप्ट में उपयोग कर सकते हैं। बस इसे स्क्रिप्ट के शीर्ष पर रखें और json_encode सामान्य रूप से काम करना जारी रखेगा।

if (version_compare(phpversion(), '7.1', '>=')) { 
    ini_set('serialize_precision', -1); 
} 
1

मुझे एक ही समस्या थी, लेकिन केवल serialize_precision = -1 समस्या को हल नहीं किया। मुझे 14 से 17 तक परिशुद्धता के मूल्य को अपडेट करने के लिए एक और कदम करना पड़ा (क्योंकि यह मेरी PHP7.0 ini फ़ाइल पर सेट किया गया था)। जाहिर है, उस संख्या के मान को बदलकर गणना की गई फ्लोट के मान को बदलता है।

1

अन्य समाधान मेरे लिए काम नहीं करते थे। मेरे कोड निष्पादन की शुरुआत में मुझे यह जोड़ना था:

if (version_compare(phpversion(), '7.1', '>=')) { 
    ini_set('precision', 17); 
    ini_set('serialize_precision', -1); 
} 
संबंधित मुद्दे