PHP-php, फ़्लोटिंग-पॉइंट, फ़्लोटिंग-सटीकता में फ़्लोटिंग पॉइंट नंबरों को समझना

मुझे पता है कि इन प्रश्नों से बहुत कुछ पूछा जा सकता है लेकिन मेरे पढ़ने और परीक्षण से मुझे थोड़ा उलझन में आया और मैंने जो कुछ पढ़ा है, उसने मुझे और अधिक जटिल बना दिया है क्योंकि यह काफी जटिल है।

कुछ लोगों को सरल तुलना के साथ समस्याएं प्रतीत होती हैं, हालांकि मुझे कोई समस्या नहीं है।

उदाहरण के लिए...

$num1 = 27.64;
$num2 = 27.64;

if ($num1 == $num2) {
echo "Good!";
} else {
echo "Bad!";
}

// Echo"s "Good!"

...तथा

$num1 = 27.60;
$num2 = 27.6;

if ($num1 == $num2) {
echo "Good!";
} else {
echo "Bad!";
}

// Echo"s Good

...तथा

$num1 = 27.60;
$num2 = 57.60;

if ($num1 <= $num2) {
echo "Good!";
} else {
echo "Bad!";
}

// Echo"s Good

...तथा

$num1 = 25.00;
$num2 = 12.50 + 12.5;

if ($num1 == $num2) {
echo "Good!";
} else {
echo "Bad!";
}

// Echo"s Good

तब मैं पेजों को देखता हूं http://patchlog.com/php/comparing-float-values-in-php/ ऐसा लगता है कि इसमें साधारण समस्याएं हैं और मुझे यह नहीं मिला।

मैं सिर्फ यह समझना चाहता हूं कि उसे अपने सरल कोड के साथ समस्याएं कैसे मिल रही हैं लेकिन मैं अपने साथ नहीं हूं।

उत्तर:

जवाब के लिए 3 № 1

उदाहरण 1

वे मान समान होंगे - आप प्रत्येक चर के लिए दशमलव दशमलव अक्षर असाइन करते हैं। इस कोड से तुलना करें:

$num1 = 27.64;
$num2 = 10.0 + 2.88 + 2.88 + 2.88 + 9.0; //In decimal arithmetic adds to 27.64

if ($num1 == $num2) {
echo "Good!";
} else {
echo "Bad!";
}

// Echo"s "Bad!"

$ num2 ऐसा लगता है कि यह 27 होना चाहिए।64, लेकिन यह वास्तव में 27.639 99 99 99 99 9997015720509807579219341278076171875 (जो कि मैं अपनी मशीन पर विजुअल सी ++ में उस गणना में करता हूं) में कुछ जोड़ता हूं। $ Num1 = 27.6400000000000005684341886080801486968994140625 (मेरी मशीन पर), इसलिए वे भिन्न होते हैं।

उदाहरण 2

पिछला 0 कोई फर्क नहीं पड़ता।

उदाहरण 3

संख्याएं फ्लोटिंग-पॉइंट "सहिष्णुता" के भीतर नहीं हैं, इसलिए निश्चित रूप से अलग-अलग होंगे।

उदाहरण 4

12.5 फ्लोटिंग पॉइंट में बिल्कुल प्रतिनिधित्व योग्य है, इसलिए 12.5 + 12.5 भी है (0.5 2 ^ -1 है)।


जवाब के लिए 2 № 2

यहां एक स्पष्ट उदाहरण दिया गया है:

$a = 0;
for ($i = 0; $i < 100000; $i++) {
$a += 0.00001;
}
print("$an");

आप उम्मीद करेंगे कि आपको मिल जाएगा 1 मुद्रित, लेकिन वास्तव में उत्पादन है 0.99999999999808

(परिणाम x86_64 आर्किटेक्चर पर है)


उत्तर № 3 के लिए 1

फ़्लोटिंग पॉइंट नंबर जितना बड़ा (या छोटा), उतना ही कम सटीक है। प्रोसेसर आर्किटेक्चर के आधार पर सटीक रूप से कितना सटीक होगा।

1E30 या 1E-30 पर अपने सभी परीक्षण करने का प्रयास करें ...


उत्तर के लिए 1 № 4

पहले दो में कंपाइलर द्वारा प्रदान किया गया मान होता है, जो दोनों संख्याओं को एक ही बिट पैटर्न में हल कर रहा है।

मैं तीसरे को छूने वाला नहीं हूं क्योंकि यह स्पष्ट होना चाहिए कि यह क्यों काम करता है।

चौथे के लिए, इस्तेमाल किए गए मानों में अच्छी तरह से परिभाषित, पूरी तरह से सटीक बिट पैटर्न होते हैं। पीटा पथ से थोड़ा अधिक संख्याओं का उपयोग करने का प्रयास करें।


जवाब के लिए 0 № 5

तुम कोशिश कर सकते हो

 $a = "12.30";

सटीक मिलान प्राप्त करने के लिए स्ट्रिंग के रूप में अन्यथा फ्लोटबॉक्स डिफ़ॉल्ट रूप से "0" को हटा दें।


जवाब के लिए 0 № 6

फ़्लोटिंग-पॉइंट त्रुटियां केवल तभी होती हैं जब वहां होंसंचालन जिनके गणितीय परिणामों को वास्तव में फ़्लोटिंग पॉइंट में प्रदर्शित नहीं किया जा सकता है। त्रुटियों को ठीक से परिभाषित किया गया है; वे यादृच्छिक या मनमानी नहीं हैं, इसलिए समान संचालन किए जाने पर समान परिणाम उत्पन्न होते हैं।

आपके पहले उदाहरण में, आप "27" असाइन करते हैं।64 "से $ num1 और $ num2 तक। यहां एक ऑपरेशन किया जा रहा है: पार्सर को वर्ण स्ट्रिंग "27.64" की व्याख्या करनी चाहिए और एक फ़्लोटिंग-पॉइंट परिणाम उत्पन्न करना चाहिए। संभावना है कि पार्सर फ्लोटिंग-पॉइंट नंबर उत्पन्न करता है जो 27.64 के करीब है। (हेक्साडेसिमल फ्लोटिंग-पॉइंट अंक के रूप में, वह संख्या 0x1.ba3d70a3d70a4p + 4 है। "पी" से पहले का हिस्सा एक हेक्साडेसिमल अंक है, जो एक आंशिक भाग के साथ होता है। "पी 4" का अर्थ 2 से गुणा करना है4। एक दशमलव अंक के रूप में, यह 27 है।6400000000000005684341886080801486968994140625.) और यह दोनों मामलों में एक ही संख्या का उत्पादन करता है, इसलिए $ num1 से $ num2 की तुलना इंगित करती है कि वे एक दूसरे के बराबर हैं, हालांकि न तो 27.64 के बराबर है (क्योंकि 27.64 को फ़्लोटिंग पॉइंट में बिल्कुल प्रतिनिधित्व नहीं किया जा सकता है)।

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

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

आपके चौथे उदाहरण में, सभी मान हैंफ्लोटिंग-पॉइंट में बिल्कुल प्रतिनिधित्व करने योग्य, इसलिए कोई त्रुटि नहीं है। 25, 12.50, और 12.5 दो की शक्ति के सभी छोटे गुणक हैं (जिसमें नकारात्मक एक्सपोनेंट के साथ शक्तियां शामिल हैं, जैसे .5 = 2-1, फ्लोटिंग-पॉइंट प्रकार की सीमा के भीतर, तोवे प्रतिनिधित्व योग्य हैं। इसके अलावा, 12.50 और 12.5 का योग बिल्कुल प्रतिनिधित्व करने योग्य है, इसलिए उन्हें जोड़ने पर कोई गोल त्रुटि नहीं है। इस प्रकार, सभी परिणाम सटीक हैं, और तुलना इंगित करती है कि योग 25 के बराबर है।

जब लोग समान उम्मीद करते हैं तो समस्याएं उत्पन्न होती हैंदो अलग-अलग गणनाओं के परिणाम जो समान गणितीय परिणाम होंगे। एक क्लासिक उदाहरण ".3" से ".1 + .2" की तुलना कर रहा है। अंक ".3" को फ़्लोटिंग-पॉइंट में कनवर्ट करने से निकटतम प्रतिनिधित्व योग्य मूल्य उत्पन्न होता है, जो 0x1.3333333333333p-2 (0.299999999999999988897769753748434595763683319091796875) है, थोड़ा नीचे .3। ".1" को फ़्लोटिंग-पॉइंट में कनवर्ट करना निकटतम प्रतिनिधित्व योग्य मूल्य उत्पन्न करता है, जो 0x1.999999999999ap-4 (0.1000000000000000055511151231257827021181583404541015625) है, थोड़ा अधिक .1। ".2" को फ़्लोटिंग-पॉइंट में कनवर्ट करना निकटतम प्रतिनिधित्व योग्य मूल्य उत्पन्न करता है, जो 0x1.999999999999ap-3 (0.200000000000000011102230246251565404236316680908203125) थोड़ा सा है .2। बाद वाले दो मान जोड़ना उनके योग के निकटतम मूल्यवान मूल्य उत्पन्न करता है, जो 0x1.3333333333334p-2 (0.3000000000000000444089209850062616169452667236328125) है। जैसा कि आप देख सकते हैं, वह योग ".3" को फ़्लोटिंग-पॉइंट में परिवर्तित करके प्राप्त मूल्य से अलग है, इसलिए उनकी तुलना करना इंगित करता है कि वे असमान हैं।


संबंधित सवाल
सबसे लोकप्रिय