दिलचस्प पोस्ट
कॉलम (एस) द्वारा एक डाटाफ्रेम को कैसे सॉर्ट करना है? मैं डिवेल सहित div को बदलने के लिए jQuery.load का उपयोग कैसे कर सकता हूं? रेल 3 में बल्क डालें कैसे कार्यान्वित करें हम PHP ऑब्जेक्ट ऑपरेटर "->" में कहां उपयोग करते हैं? सी # में प्रारूप की तारीख क्यों <center> टैग HTML में बहिष्कृत है? जावास्क्रिप्ट लूप: के लिए … बनाम के लिए जावास्क्रिप्ट के साथ iframe src बदल रहा है मैं एक पाठ फ़ाइल के एन्कोडिंग / कोडपेज का पता कैसे लगा सकता हूं? android.content.ActivityNotFoundException: Android साझा वरीयताएँ उदाहरण आईओएस एप के लिए "ओपन इन …" विकल्प जोड़ना कैसे फाइल सिस्टम समवर्ती पढ़ा / लिखते हैं? पायथन: प्रकार एरर: 'स्ट्र' और 'इंट' ऑब्जेक्ट्स को जोड़ नहीं सकते हैं 5 जीबी से बड़ा फाइल के लिए अमेज़ॅन-एस 3 इटाग की गणना करने के लिए एल्गोरिथ्म क्या है?

मुझे फ्लोटिंग प्वाइंट तुलना कैसे करनी चाहिए?

मैं वर्तमान में कुछ कोड लिख रहा हूं जहां पर मेरे पास कुछ है:

double a = SomeCalculation1(); double b = SomeCalculation2(); if (a < b) DoSomething2(); else if (a > b) DoSomething3(); 

और फिर अन्य जगहों पर मुझे समानता करने की आवश्यकता हो सकती है:

 double a = SomeCalculation3(); double b = SomeCalculation4(); if (a == 0.0) DoSomethingUseful(1 / a); if (b == 0.0) return 0; // or something else here 

संक्षेप में, मेरे पास बहुत सारे अस्थायी बिंदु गणित चलते हैं और मुझे परिस्थितियों के लिए विभिन्न तुलना करने की आवश्यकता है I मैं इसे पूर्णांक गणित में परिवर्तित नहीं कर सकता क्योंकि इस संदर्भ में ऐसी कोई बात व्यर्थ नहीं है।

मैंने पढ़ा है इससे पहले कि फ्लोटिंग प्वाइंट तुलना अविश्वसनीय हो सकती है, क्योंकि आपके पास इस तरह की चीज़ें हो सकती हैं:

 double a = 1.0 / 3.0; double b = a + a + a; if ((3 * a) != b) Console.WriteLine("Oh no!"); 

संक्षेप में, मैं जानना चाहूंगा: कैसे मैं मज़बूती से फ्लोटिंग प्वाइंट नंबर (कम से कम, समानता) की तुलना कर सकता हूं?

मैं जिस संख्या की सीमा का उपयोग कर रहा हूं वह मोटे तौर पर 10 ई -14 से 10 ई 6 तक है, इसलिए मुझे छोटी संख्या के साथ-साथ बड़े रूप में काम करने की ज़रूरत है।

मैंने इसे भाषा अज्ञेयवादी के रूप में टैग किया है क्योंकि मुझे इसमें दिलचस्पी है कि मैं इसे कैसे पूरा कर सकता हूं, इससे कोई फर्क नहीं पड़ता कि मैं किस भाषा का उपयोग कर रहा हूं।

Solutions Collecting From Web of "मुझे फ्लोटिंग प्वाइंट तुलना कैसे करनी चाहिए?"

अधिक / छोटे के लिए तुलना करना वास्तव में एक समस्या नहीं है जब तक कि आप फ्लोट / डबल सटीक सीमा के ठीक किनारे पर काम नहीं कर रहे हैं

तुलना करने के लिए "फजी बराबर" की तुलना में, यह (जावा कोड को अनुकूलित करना आसान होना चाहिए) मैं बहुत सारे काम के बाद फ़्लोटिंग-प्वाइंट गाइड के साथ आया हूं और कई आलोचनाओं को ध्यान में रखता हूं:

 public static boolean nearlyEqual(float a, float b, float epsilon) { final float absA = Math.abs(a); final float absB = Math.abs(b); final float diff = Math.abs(a - b); if (a == b) { // shortcut, handles infinities return true; } else if (a == 0 || b == 0 || diff < Float.MIN_NORMAL) { // a or b is zero or both are extremely close to it // relative error is less meaningful here return diff < (epsilon * Float.MIN_NORMAL); } else { // use relative error return diff / (absA + absB) < epsilon; } } 

यह एक परीक्षण सूट के साथ आता है। आपको तत्काल किसी भी समाधान को बर्खास्त करना चाहिए, क्योंकि यह वस्तुतः कुछ किनारे मामलों में असफल होने की गारंटी देता है जैसे कि एक मान 0, शून्य के विपरीत दो बहुत कम मूल्य, या असंबद्धताएं।

एक वैकल्पिक (अधिक विवरण के लिए ऊपर दिए गए लिंक देखें) फ्लोट के बिट पैटर्न को पूर्णांक में कनवर्ट करना और एक निश्चित पूर्णांक दूरी के भीतर सब कुछ स्वीकार करना है।

किसी भी मामले में, शायद कोई भी समाधान नहीं है जो सभी अनुप्रयोगों के लिए एकदम सही है। आदर्श रूप से, आप अपने वास्तविक उपयोग के मामलों को कवर करने वाले एक परीक्षण सूट के साथ खुद को विकसित / अनुकूलित करेंगे।

फ्लोटिंग प्वाइंट नंबर A < B और A > B की तुलना करने में मुझे समस्या थी I

 if(A - B < Epsilon) && (fabs(AB) > Epsilon) { printf("A is less than B"); } if (A - B > Epsilon) && (fabs(AB) > Epsilon) { printf("A is greater than B"); } 

फ़ैब्स – निरपेक्ष मूल्य – यदि वे अनिवार्य रूप से बराबर हैं तो उनका ख्याल रखता है।

फ्लोट नंबरों की तुलना करने के लिए हमें एक सहिष्णुता स्तर चुनना होगा। उदाहरण के लिए,

 final float TOLERANCE = 0.00001; if (Math.abs(f1 - f2) < TOLERANCE) Console.WriteLine("Oh yes!"); 

एक नोट। आपका उदाहरण बल्कि हास्यास्पद है।

 double a = 1.0 / 3.0; double b = a + a + a; if (a != b) Console.WriteLine("Oh no!"); 

यहाँ कुछ गणित

 a = 1/3 b = 1/3 + 1/3 + 1/3 = 1. 1/3 != 1 

अरे हाँ..

क्या मतलब है आपका

 if (b != 1) Console.WriteLine("Oh no!") 

आइडिया मुझे फ्लोटिंग प्वाइंट की तुलना स्विफ्ट में हुई थी

 infix operator ~= {} func ~= (a: Float, b: Float) -> Bool { return fabsf(a - b) < Float(FLT_EPSILON) } func ~= (a: CGFloat, b: CGFloat) -> Bool { return fabs(a - b) < CGFloat(FLT_EPSILON) } func ~= (a: Double, b: Double) -> Bool { return fabs(a - b) < Double(FLT_EPSILON) } 

टी एल; डॉ

कुछ सीमा मामलों में कुछ अवांछनीय परिणामों से बचने के लिए माइकल बोर्गवर्ट के बजाय निम्न फ़ंक्शन का उपयोग करें।

 bool nearlyEqual(float a, float b, float epsilon = 0.00001f, float relth = std::numeric_limits<float>::min()) { assert(0.f < epsilon); assert(epsilon < 1.f); if (a == b) return true; auto diff = std::abs(ab); auto norm = std::min((std::abs(a) + std::abs(b)), std::numeric_limits<float>::max()); return diff < epsilon * std::max(relth, norm); } 

मूल पोस्ट

माइकल बोर्गवार्ट का जवाब महान है लेकिन अभी भी एक दोष से ग्रस्त है। पहले की तुलना में दूसरी जोड़ी के सदस्यों के बीच एक बड़ा अंतर है, और फिर भी, दूसरे जोड़े की संख्या के अनुसार, परिमाण के समान क्रम के साथ दो जोड़े संख्या (a1, b1) और (a2, b2) मिलना संभव है बराबर समझा और पहले नहीं

उदाहरण के लिए, 1e-5 एक epsilon के लिए,

 (a1, b1) = (1.175494865101066e-032, 1.175493836543509e-032) (a2, b2) = (1.1755049302714449e-032, 1.1754837713731301e-032) 

ये दो जोड़े जाहिर परिमाण के एक ही क्रम के बारे में हैं – वास्तव में, अर्थ में सख्ती से बराबर |a1+b1|=|a2+b2| । उनके मतभेद,

 |a1-b1| = 1.0285575569695016e-038 |a2-b2| = 2.1158898314801175e-037 

व्यापक रूप से अलग हैं: दूसरे और प्रथम के बीच 20 से अधिक कारक और फिर भी,

 nearlyEqual(a1,b1,1e-5) = false nearlyEqual(a2,b2,1e-5) = true 

यह व्यवहार समारोह में असंतुलन के कारण है Float.MIN_NORMAL बारे में Float.MIN_NORMAL भटकती है। Float.MIN_NORMAL और फ़ंक्शन केवल एक छोटी सी दिशा में दूसरे Float.MIN_NORMAL स्विच कर सकता है, इसमें कोई गारंटी नहीं है कि दोनों शाखाएं समान हैं और उसी परिणाम को वापस लौटा देंगे।

वर्तमान में यह केवल अपेक्षाकृत छोटी संख्या के लिए हो सकता है हालांकि यह हमेशा Float.MIN_NORMAL रूप में इस तरह के एक छोटे पैमाने पर रिश्तेदार से अलग अंतर स्विच करने के लिए समझ में नहीं आता है। Float.MIN_NORMAL , और वास्तव में एक बहुत अधिक मूल्यों पर स्विच जगह करना चाहते हो सकता है, जैसा कि यहां बताया गया है फिर यह असंतुलन "अधिक सामान्य" जोड़े में अपंग हो सकता है

निरंतरता सुनिश्चित करने के लिए, संभवतः पोस्टिंग के शीर्ष पर दिए गए फ़ंक्शन में, शाखा का परीक्षण बदलने के लिए सबसे आसान तय है

नया relth पैरामीटर नियंत्रित करता है, जिस पर कोई रिश्ते से पूर्ण तुलना करने के लिए स्विच करना चाहता है।

इस परीक्षण की व्याख्या बल्कि सरल है। मूल-केन्द्रित वर्ग के बाहर |a| + |b| == relth |a| + |b| == relth |a| + |b| == relth , डिफ़ॉल्ट सापेक्ष तुलना लेता है। इस वर्ग के भीतर, इसके बजाय एक पूर्ण तुलना का उपयोग किया जाता है, और दहलीज को लिया जाता है ताकि प्रतिक्रिया फ़ंक्शन निरंतर हो।

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

संपादित करें

चेतावनी: गणितीय आगे बढ़ते हुए

अब मुझे एहसास है कि फ़ंक्शन के विभिन्न उपडोमेन के बीच की सीमा के निकट प्रतिक्रिया की असंतुलन संभावित सुधार का संकेत हो सकता है लेकिन समस्या के स्रोत के प्रति नहीं हो सकता है। इसके अलावा, तथ्य यह है कि |a+b|=|c+d| और |ab| < |cd| |ab| < |cd| इसका अर्थ यह होना चाहिए कि यदि c=~d तब a=~b (चलो यह गुण पी कहते हैं) हो सकता है लेकिन यह थोड़ा सा भी स्पष्ट है। शायद यह सम्पत्ति अधिक सीधे-सीधे वांछनीय संपत्तियों से आ सकती है, जो कि "निकट-समानता" समारोह =~ आवश्यकता होनी चाहिए।

निम्नलिखित गुण हैं कि =~ होना चाहिए बल्कि स्पष्ट है:

  • आत्म-समानता: a=~a
  • समरूपता: a=~b का तात्पर्य b=~a
  • विपक्ष के द्वारा अचेतन: a=~b का तात्पर्य (-a)=~(-b)

(हम a=~b और b=~c है a=~c , तो =~ एक तुल्यता संबंध नहीं है) नहीं है।

मैं निम्नलिखित गुण जोड़ूंगा जो कि अस्थायी बिंदु तुलना के लिए अधिक विशिष्ट हैं;

  • यदि a<b<c , तब a=~c का अर्थ है a=~b (करीब मान समान होना चाहिए)
  • यदि a,b,m>=0 तब a=~b अर्थ है (a+m)=~(b+m) (समान अंतर के साथ बड़ा मूल्य भी बराबर होना चाहिए)

नोट करें कि प्रॉपर्टी पी को इस पहली संपत्ति (सममिति और invariance के साथ) से घटाया जा सकता है, इसलिए ऊपर दिए गए संख्यात्मक काउंटरटेक्साम को सभी के बाद अपर्याप्त नहीं था।

उन गुणों को पहले से ही संभावित निकट-समता कार्यों पर मजबूत प्रतिबंध लगा दिया गया है। मैंने प्रस्तावित समारोह उन्हें सत्यापित किया। शायद एक या कई अन्यथा स्पष्ट गुण गायब हैं। यदि कोई यह इंगित करेगा कि असमान जोड़े के सेट के जुड़ा घटकों उत्तल (किसी तरह मुझे लगता है कि ऐसा होना चाहिए) तो यह महान होगा इसके अलावा विपरीत संकेत के मूल्यों पर प्रतिक्रियाओं पर रोकें वर्तमान में महान नहीं है मैं पिछले एक को बदलने के साथ प्यार करेंगे

  • यदि b,m>=0 , a>=-b तब a=~b का तात्पर्य (a+m)=~(b+m)

लेकिन यह वास्तव में सरल नहीं लगता है

एक भी एपिसलॉन के पैरामीटरेड निकट-समान रिश्तों =~_eps परिवारों पर गुण हो सकते हैं, उदाहरण के लिए

  • यदि eps1 < eps2 तब a =~_eps1 b का अर्थ है a =~_eps2 b

मैं प्रस्ताव समारोह भी यह पुष्टि करता है।

मानक सलाह कुछ छोटे "एपिसलॉन" मूल्य (संभवतः आपके आवेदन के आधार पर चुना जाता है) का उपयोग करना है, और एक दूसरे के एपसीलॉन के भीतर समान समान होने के लिए फ़्लोट्स पर विचार करना है। जैसे कुछ जैसे

 #define EPSILON 0.00000001 if ((a - b) < EPSILON && (b - a) < EPSILON) { printf("a and b are about equal\n"); } 

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

माइकल बोरगार्ड और बोसोनिक्स के उत्तर से PHP के अनुकूलन:

 class Comparison { const MIN_NORMAL = 1.17549435E-38; //from Java Specs // from http://floating-point-gui.de/errors/comparison/ public function nearlyEqual($a, $b, $epsilon = 0.000001) { $absA = abs($a); $absB = abs($b); $diff = abs($a - $b); if ($a == $b) { return true; } else { if ($a == 0 || $b == 0 || $diff < self::MIN_NORMAL) { return $diff < ($epsilon * self::MIN_NORMAL); } else { return $diff / ($absA + $absB) < $epsilon; } } } } 

मैं हाल ही में एक समान समस्या के माध्यम से ठोकर दे रहा हूं, और कुछ परीक्षण कर रहा हूं।

कुछ मामलों में यदि दो फ़्लोट्स का एक ही स्ट्रिंग मान होता है तो वो फ्लोट्स ( (float)$float1 === (float)$float2) , (float)$float1 === (float)$float2) मुकाबले तुलना में तुलनात्मक रूप से समान हो जाएगा, चाहे वे कैसे व्युत्पन्न हों। हालांकि अन्य मामलों में, भले ही दो फ़्लोट्स के पास एक ही स्ट्रिंग मान हो, वे कभी-कभी अपेक्षाकृत भिन्न रूप से लौटते हैं जब फ़्लोट्स की तुलना में तुलना की जाती है यदि वे अलग-अलग तरीके से प्राप्त होते हैं।

कृपया नीचे दिए गए उदाहरण देखें:

 $float1 = 0.04 + 0.02; $float2 = 0.04 + 0.01 + 0.01; $float3 = 0.03 + 0.03; echo 'Values:'; var_dump($float1); echo '<br>'; var_dump($float2); echo '<br>'; var_dump($float3); echo '<br><br>'; echo 'Comparisons:'; var_dump($float1 - $float2); echo '<br>'; var_dump($float2 - $float3); echo '<br>'; var_dump($float1 - $float3); echo '<br>'; 

PHP 5.3 पर चलाना, इसका परिणाम है:

मान:

नाव (0.06)

नाव (0.06)

नाव (0.06)

तुलना:

नाव (-6.93889390391E-18)

नाव (6.93889390391E-18)

नाव (0)

जैसे कि आप देख सकते हैं, $ float2 फ्लोट के रूप में तुलना में $ float1 और $ float3 के समान नहीं है उनके बीच एकमात्र अंतर है कि वे कैसे व्युत्पन्न हुए। आप सोचेंगे कि यह समझने में समझ में आता है कि यह कोई फर्क नहीं पड़ेगा कि फ्लोट कैसे निकला था, केवल इसका अंतिम मूल्य क्या है, लेकिन ऊपर के उदाहरण से आप देख सकते हैं कि यह एक बुरा धारणा है।

वास्तविक अंतर इतना मामूली है कि यह गणना करने के लिए वास्तव में कोई मायने नहीं रखता, लेकिन उनकी तुलना करते समय यह मामला नहीं होता है।

यदि आप फ्लोट्स को आत्मविश्वास से फ़्लोट्स के रूप में तुलना करना चाहते हैं, तो यहां कुछ भी तुलना करने से पहले मैं सुझाव देता हूं:

 $float1 = 0.04 + 0.02; $float2 = 0.04 + 0.01 + 0.01; $float3 = 0.03 + 0.03; //Cast to string, then back to float $float1 = (float)(string)$float1; $float2 = (float)(string)$float2; $float3 = (float)(string)$float3; echo 'Values:'; var_dump($float1); echo '<br>'; var_dump($float2); echo '<br>'; var_dump($float3); echo '<br><br>'; echo 'Comparisons:'; var_dump($float1 - $float2); echo '<br>'; var_dump($float2 - $float3); echo '<br>'; var_dump($float1 - $float3); echo '<br>'; 

मान:

नाव (0.06)

नाव (0.06)

नाव (0.06)

तुलना:

नाव (0)

नाव (0)

नाव (0)

मुझे लगता है कि इस मुद्दे से एक फ्लोट के घटक हिस्से को कंप्यूटर पर द्विआधारी में संग्रहीत करने के लिए अलग परिशुद्धता के साथ गोल किया जाता है। यदि आप स्ट्रिंग में डालें तो फिर एक फ्लोट पर फिर से, राउंडिंग को अंतिम मान पर किया जाता है ताकि अंतिम मूल्यों में एक ही स्ट्रिंग मान हो, उनकी फ्लोट वैल्यू भी हमेशा समान रहें।

उम्मीद है की वो मदद करदे।

संपादित करें:

मैं अभी बीसी (बाइनरी गणना) में आया हूँ php.net पर मठ फ़ंक्शन। ये ऊपर की तरह ही प्राप्त करने लगते हैं, फिर भी वे स्ट्रिंग मान वापस लौटते हैं, यदि आप फ्लोट करना चाहते हैं, तो सुनिश्चित करें कि आप बाद में फ़्लोट्स पर वापस आ गए हैं। यहां दस्तावेज़ीकरण है: http://php.net/manual/en/ref.bc.php

निचे देखो:

 echo '$float1 - $float2 = '; var_dump(bcsub($float1,$float2,2)); echo '<br>'; echo '$float2 - $float3 = '; var_dump(bcsub($float2,$float3,2)); echo '<br>'; echo '$float1 - $float3 = '; var_dump(bcsub($float1,$float3,2)); echo '<br>'; 

यह दिखाता है:

$ फ्लोट 1 – $ फ्लोट 2 = स्ट्रिंग (4) "0.00"

$ float2 – $ float3 = स्ट्रिंग (4) "0.00"

$ float1 – $ float3 = स्ट्रिंग (4) "0.00"

समानता / असमानता के लिए डबल्स की तुलना करने का सबसे अच्छा तरीका उनके अंतर के पूर्ण मूल्य को लेना और इसे अपने छोटे से (आपके संदर्भ के आधार पर) मूल्य की तुलना करना है।

 double eps = 0.000000001; //for instance double a = someCalc1(); double b = someCalc2(); double diff = Math.abs(a - b); if (diff < eps) { //equal } 

मैंने मन में उपरोक्त टिप्पणियों के साथ एक समानता समारोह लिखने की कोशिश की यहां बताया गया है कि मैं किसके साथ आया हूं:

संपादित करें: मठ से बदलें। मैक्स (ए, बी) से मठ। अधिकतम (मठ। एब्स (ए), मठ। एब्स (बी))

 static bool fpEqual(double a, double b) { double diff = Math.Abs(a - b); double epsilon = Math.Max(Math.Abs(a), Math.Abs(b)) * Double.Epsilon; return (diff < epsilon); } 

विचार? मुझे अभी भी एक से अधिक काम करने की आवश्यकता है, और कम से कम भी।

आप को ध्यान में रखना चाहिए कि truncation त्रुटि एक रिश्तेदार है दो संख्याएं लगभग समान हैं यदि उनके अंतर के बारे में जितना बड़ा उनके उलटे (यूनिट में अंतिम स्थान) है।

हालांकि, यदि आप फ्लोटिंग प्वाइंट की गणना करते हैं, तो आपकी त्रुटि क्षमता प्रत्येक ऑपरेशन (विशेषकर घटाव के साथ सावधान!) के साथ बढ़ जाती है, इसलिए आपके त्रुटि सहिष्णुता को तदनुसार बढ़ाने की आवश्यकता है।

अगर किसी को देखना है कि फ्लोट की तुलना क्यों खराब है, यह PHP में एक उदाहरण है जिसे मैंने आज हिट किया। PHP यह काफी भ्रामक बनाता है क्योंकि यह प्रिंट करता है जो समान मानों को तारों के समान दिखता है। यह देखने के लिए कि क्या गलत हो गया था, आपको उच्च परिशुद्धता के साथ प्रिंट करना होगा।

निम्न स्क्रिप्ट अंततः विफल हो जाएगी, हालांकि हम अनंत लूप में हैं। आप देख सकते हैं कि दो स्ट्रिंग्स के कुछ उपयोगों के लिए ऐसा प्रतीत होता है जैसे वे वही मान हैं, वे समान नहीं हैं, $secs प्रकार एक फ्लोट है (मुझे पता है कि इसे डबल के रूप में प्रिंट होता है)।

 <?php while(1) { $time = time(); $millis = $time * 1000; $hours = $millis / 3600000; $mins = $hours * 60; //$secs = (int)($mins * 60); $secs = ($mins * 60); printf("gettype(time) == %s\n", gettype($time)); printf("gettype(secs) == %s\n", gettype($secs)); printf("$time == $secs\n", $time, $secs); printf("%d == %d\n", $time, $secs ); printf("%f == %f\n", $time, $secs ); printf("%.1f == %.1f\n", $time, $secs ); printf("%.10f == %.10f\n", $time, $secs ); printf("%.10F == %.10F\n", $time, $secs ); printf("%b == %b\n", $time, $secs ); assert($secs == $time); if($secs != $time) { break; } }