दिलचस्प पोस्ट
कैसे एक ऑटो वृद्धि संस्करण संख्या (दृश्य स्टूडियो) है? PHP SimpleXMlelement सरणी से मूल्य प्राप्त करें निर्धारित करें कि किस विन्यास फाइल का उपयोग किया जा रहा है एंड्रॉइड एप्लिकेशन में बुलेटेड सूची कैसे जोड़ें? एकाधिक स्तंभ समुच्चय के साथ SQL सर्वर पिवोट तालिका EXC_BAD_ACCESS संकेत मिला प्रारंभिक चाल में स्वामी को गिट में किसी अन्य शाखा में ले जाता है जावास्क्रिप्ट के साथ फोन नंबर मान्य करें क्या टुकड़ों को वाकई एक खाली कन्स्ट्रक्टर की ज़रूरत है? कोर ग्राफिक्स वस्तुओं के साथ एआरसी काम करता है? सामान्य के लिए ट्रांसफार्म एक्स्प्शन डुप्लिकेट प्रविष्टि.नोटेशन। बीटा दिनांक प्रारूप पार्स अपवाद – "ईईई एमएमएम डीडी एच एच: एमएम: एसएस जेड य्याय" जावा में एक अर्रे पर सूची का उपयोग कब करना है? एक क्वेरी में एएनएसआई 1992 के जॉन्स और कमांड्स को मिलाते हुए 2 दशमलव स्थानों पर एक फ्लोटेटिंग फ़ॉर्मेट करना

फ्लोट और डबल तुलना का सबसे प्रभावी तरीका क्या है?

दो double या दो float मूल्यों की तुलना करने का सबसे कारगर तरीका क्या होगा?

बस ऐसा करना सही नहीं है:

 bool CompareDoubles1 (double A, double B) { return A == B; } 

लेकिन कुछ ऐसा:

 bool CompareDoubles2 (double A, double B) { diff = A - B; return (diff < EPSILON) && (-diff < EPSILON); } 

प्रसंस्करण बर्बाद करने के लिए लगता है

क्या कोई चालाक नाव की तुलना करता है?

वेब के समाधान से एकत्रित समाधान "फ्लोट और डबल तुलना का सबसे प्रभावी तरीका क्या है?"

अन्य सुझावों में से किसी का उपयोग करके सावधान रहें यह सब संदर्भ पर निर्भर करता है

मैंने एक लंबे समय से एक प्रणाली में एक बग का पता लगाया है जो कि a==b मानी जाती a==b अगर |ab|<epsilon अंतर्निहित समस्याएं थीं:

  1. एक एल्गोरिथ्म में अंतर्निहित अनुमान है कि यदि a==b और b==c फिर a==c

  2. मिल्स (.001 इंच) में मापा इंच और लाइनों में मापा लाइनों के लिए एक ही एप्सिलॉन का उपयोग करना यह a==b लेकिन 1000a!=1000b a==b (यही कारण है कि लगभग सभी एक्सेल 2 के पूरक एप्सिलॉन या अधिकतम यूएलपीएस के लिए पूछते हैं)

  3. कोण के कोसाइन और लाइनों की लंबाई दोनों के लिए एक ही एप्सिलॉन का उपयोग!

  4. संग्रह में आइटमों को क्रमबद्ध करने के लिए इस तरह की एक तुलनात्मक फ़ंक्शन का उपयोग करना। (दुर्गों के लिए निर्मित सी C + + ऑपरेटर == का उपयोग करके इस मामले में सही परिणाम उत्पन्न होते हैं।)

जैसे मैंने कहा: यह सब संदर्भ पर निर्भर करता a और b और b के अपेक्षित आकार पर निर्भर करता है।

BTW, std::numeric_limits<double>::epsilon() "मशीन एपिसलॉन" है। यह 1.0 के बीच का अंतर है और अगले मूल्य को दोहरे द्वारा दिखाया जा सकता है। मुझे लगता है कि इसका उपयोग तुलना समारोह में किया जा सकता है, लेकिन सिर्फ अगर उम्मीद मान 1 से कम है। (यह @ सीडीवी के उत्तर के जवाब में है …)

इसके अलावा, यदि आपके पास मूल रूप से doubles में int अंकगणित है (यहां हम कुछ मामलों में डायल के लिए इंट वैल्यू रखने के लिए उपयोग करते हैं) तो आपके अंकगणित सही होंगे। उदाहरण के लिए 4.0 / 2.0 1.0 + 1.0 के समान होगा। यह तब तक है जब तक आप चीजें नहीं करते जो परिणाम (4.0 / 3.0) में भिन्न होती हैं या किसी int के आकार के बाहर नहीं जाते हैं

एक एप्सिलॉन मूल्य के साथ तुलना यह है कि ज्यादातर लोग क्या करते हैं (गेम प्रोग्रामिंग में भी)

आपको अपने कार्यान्वयन को थोड़ा बदलना चाहिए:

 bool AreSame(double a, double b) { return fabs(a - b) < EPSILON; } 

संपादित करें: हालिया ब्लॉग पोस्ट पर क्रिस्टस्टर ने इस विषय पर बहुत अच्छी जानकारी का स्टैक जोड़ा है का आनंद लें।

मैंने पाया कि Google C ++ परीक्षण फ़्रेमवर्क में अलौकिक एक्वल 2 के लिए एक अच्छा क्रॉस-प्लेटफ़ॉर्म टेम्पलेट-आधारित कार्यान्वयन शामिल है जो दोनों युगल और फ़्लोट्स पर काम करता है यह देखते हुए कि यह बीएसडी लाइसेंस के तहत जारी किया गया है, इसे अपने खुद के कोड में प्रयोग करने से कोई समस्या नहीं होनी चाहिए, जब तक आप लाइसेंस नहीं रख सकते मैंने नीचे दिए गए कोड को http://code.google.com/p/googletest/source/browse/trunk/include/gtest/internal/gtest-internal.h से निकाला और शीर्ष पर लाइसेंस जोड़ा।

सुनिश्चित करें कि कुछ मान के लिए GTEST_OS_WINDOWS को परिभाषित करें (या उस कोड को बदलने के लिए जहां इसे आपके कोडबेस में फिट करने के लिए उपयोग किया जाता है – यह सभी के बाद बीएसडी लाइसेंस प्राप्त है)।

उपयोग का उदाहरण:

 double left = // something double right = // something const FloatingPoint<double> lhs(left), rhs(right); if (lhs.AlmostEquals(rhs)) { //they're equal! } 

यहां कोड है:

 // Copyright 2005, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee) // // The Google C++ Testing Framework (Google Test) // This template class serves as a compile-time function from size to // type. It maps a size in bytes to a primitive type with that // size. eg // // TypeWithSize<4>::UInt // // is typedef-ed to be unsigned int (unsigned integer made up of 4 // bytes). // // Such functionality should belong to STL, but I cannot find it // there. // // Google Test uses this class in the implementation of floating-point // comparison. // // For now it only handles UInt (unsigned int) as that's all Google Test // needs. Other types can be easily added in the future if need // arises. template <size_t size> class TypeWithSize { public: // This prevents the user from using TypeWithSize<N> with incorrect // values of N. typedef void UInt; }; // The specialization for size 4. template <> class TypeWithSize<4> { public: // unsigned int has size 4 in both gcc and MSVC. // // As base/basictypes.h doesn't compile on Windows, we cannot use // uint32, uint64, and etc here. typedef int Int; typedef unsigned int UInt; }; // The specialization for size 8. template <> class TypeWithSize<8> { public: #if GTEST_OS_WINDOWS typedef __int64 Int; typedef unsigned __int64 UInt; #else typedef long long Int; // NOLINT typedef unsigned long long UInt; // NOLINT #endif // GTEST_OS_WINDOWS }; // This template class represents an IEEE floating-point number // (either single-precision or double-precision, depending on the // template parameters). // // The purpose of this class is to do more sophisticated number // comparison. (Due to round-off error, etc, it's very unlikely that // two floating-points will be equal exactly. Hence a naive // comparison by the == operation often doesn't work.) // // Format of IEEE floating-point: // // The most-significant bit being the leftmost, an IEEE // floating-point looks like // // sign_bit exponent_bits fraction_bits // // Here, sign_bit is a single bit that designates the sign of the // number. // // For float, there are 8 exponent bits and 23 fraction bits. // // For double, there are 11 exponent bits and 52 fraction bits. // // More details can be found at // http://en.wikipedia.org/wiki/IEEE_floating-point_standard. // // Template parameter: // // RawType: the raw floating-point type (either float or double) template <typename RawType> class FloatingPoint { public: // Defines the unsigned integer type that has the same size as the // floating point number. typedef typename TypeWithSize<sizeof(RawType)>::UInt Bits; // Constants. // # of bits in a number. static const size_t kBitCount = 8*sizeof(RawType); // # of fraction bits in a number. static const size_t kFractionBitCount = std::numeric_limits<RawType>::digits - 1; // # of exponent bits in a number. static const size_t kExponentBitCount = kBitCount - 1 - kFractionBitCount; // The mask for the sign bit. static const Bits kSignBitMask = static_cast<Bits>(1) << (kBitCount - 1); // The mask for the fraction bits. static const Bits kFractionBitMask = ~static_cast<Bits>(0) >> (kExponentBitCount + 1); // The mask for the exponent bits. static const Bits kExponentBitMask = ~(kSignBitMask | kFractionBitMask); // How many ULP's (Units in the Last Place) we want to tolerate when // comparing two numbers. The larger the value, the more error we // allow. A 0 value means that two numbers must be exactly the same // to be considered equal. // // The maximum error of a single floating-point operation is 0.5 // units in the last place. On Intel CPU's, all floating-point // calculations are done with 80-bit precision, while double has 64 // bits. Therefore, 4 should be enough for ordinary use. // // See the following article for more details on ULP: // http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm. static const size_t kMaxUlps = 4; // Constructs a FloatingPoint from a raw floating-point number. // // On an Intel CPU, passing a non-normalized NAN (Not a Number) // around may change its bits, although the new value is guaranteed // to be also a NAN. Therefore, don't expect this constructor to // preserve the bits in x when x is a NAN. explicit FloatingPoint(const RawType& x) { u_.value_ = x; } // Static methods // Reinterprets a bit pattern as a floating-point number. // // This function is needed to test the AlmostEquals() method. static RawType ReinterpretBits(const Bits bits) { FloatingPoint fp(0); fp.u_.bits_ = bits; return fp.u_.value_; } // Returns the floating-point number that represent positive infinity. static RawType Infinity() { return ReinterpretBits(kExponentBitMask); } // Non-static methods // Returns the bits that represents this number. const Bits &bits() const { return u_.bits_; } // Returns the exponent bits of this number. Bits exponent_bits() const { return kExponentBitMask & u_.bits_; } // Returns the fraction bits of this number. Bits fraction_bits() const { return kFractionBitMask & u_.bits_; } // Returns the sign bit of this number. Bits sign_bit() const { return kSignBitMask & u_.bits_; } // Returns true iff this is NAN (not a number). bool is_nan() const { // It's a NAN if the exponent bits are all ones and the fraction // bits are not entirely zeros. return (exponent_bits() == kExponentBitMask) && (fraction_bits() != 0); } // Returns true iff this number is at most kMaxUlps ULP's away from // rhs. In particular, this function: // // - returns false if either number is (or both are) NAN. // - treats really large numbers as almost equal to infinity. // - thinks +0.0 and -0.0 are 0 DLP's apart. bool AlmostEquals(const FloatingPoint& rhs) const { // The IEEE standard says that any comparison operation involving // a NAN must return false. if (is_nan() || rhs.is_nan()) return false; return DistanceBetweenSignAndMagnitudeNumbers(u_.bits_, rhs.u_.bits_) <= kMaxUlps; } private: // The data type used to store the actual floating-point number. union FloatingPointUnion { RawType value_; // The raw floating-point number. Bits bits_; // The bits that represent the number. }; // Converts an integer from the sign-and-magnitude representation to // the biased representation. More precisely, let N be 2 to the // power of (kBitCount - 1), an integer x is represented by the // unsigned number x + N. // // For instance, // // -N + 1 (the most negative number representable using // sign-and-magnitude) is represented by 1; // 0 is represented by N; and // N - 1 (the biggest number representable using // sign-and-magnitude) is represented by 2N - 1. // // Read http://en.wikipedia.org/wiki/Signed_number_representations // for more details on signed number representations. static Bits SignAndMagnitudeToBiased(const Bits &sam) { if (kSignBitMask & sam) { // sam represents a negative number. return ~sam + 1; } else { // sam represents a positive number. return kSignBitMask | sam; } } // Given two numbers in the sign-and-magnitude representation, // returns the distance between them as an unsigned number. static Bits DistanceBetweenSignAndMagnitudeNumbers(const Bits &sam1, const Bits &sam2) { const Bits biased1 = SignAndMagnitudeToBiased(sam1); const Bits biased2 = SignAndMagnitudeToBiased(sam2); return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1); } FloatingPointUnion u_; }; 

संपादित करें: यह पोस्ट 4 साल पुराना है। यह शायद अभी भी वैध है, और कोड अच्छा है, लेकिन कुछ लोगों ने सुधार प्राप्त किए हैं। सर्वश्रेष्ठ Google परीक्षण स्रोत कोड से AlmostEquals का नवीनतम संस्करण प्राप्त करें, और यहां पर चिपकाए गए एक नहीं।

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

फ्लोटिंग प्वाइंट तुलना की तलाश करते समय फ्लोटिंग प्वाइंट नंबर की तुलना ब्रूस डॉसन द्वारा शुरू करने के लिए एक अच्छी जगह है।

निम्नलिखित परिभाषाएं कंप्यूटर प्रोफेशनल की कला से हैं :

 bool approximatelyEqual(float a, float b, float epsilon) { return fabs(a - b) <= ( (fabs(a) < fabs(b) ? fabs(b) : fabs(a)) * epsilon); } bool essentiallyEqual(float a, float b, float epsilon) { return fabs(a - b) <= ( (fabs(a) > fabs(b) ? fabs(b) : fabs(a)) * epsilon); } bool definitelyGreaterThan(float a, float b, float epsilon) { return (a - b) > ( (fabs(a) < fabs(b) ? fabs(b) : fabs(a)) * epsilon); } bool definitelyLessThan(float a, float b, float epsilon) { return (b - a) > ( (fabs(a) < fabs(b) ? fabs(b) : fabs(a)) * epsilon); } 

बेशक, एप्सिलॉन चुनने के संदर्भ पर निर्भर करता है, और निर्धारित करता है कि आप कितने नंबरों को चाहते हैं।

फ्लोटिंग प्वाइंट नंबर की तुलना करने की एक और विधि संख्याओं के यूएलपी (अंतिम स्थान पर इकाइयां) को देखने के लिए है। तुलना के साथ विशेष रूप से निपटने के लिए, पेपर जो कुछ कंप्यूटर वैज्ञानिक को फ़्लोटिंग प्वाइंट नंबर के बारे में पता होना चाहिए कि यह समझने के लिए एक अच्छा संसाधन है कि फ़्लोटिंग प्वाइंट कैसे काम करता है और जो नुकसान हैं, जिसमें यूएलपी भी शामिल है।

गहराई से अधिक तरीके के लिए पढ़ने के लिए फ़्लोटिंग बिंदु संख्याओं की तुलना करें । उस लिंक से कोड स्निपेट यहां दिया गया है:

 // Usable AlmostEqual function bool AlmostEqual2sComplement(float A, float B, int maxUlps) { // Make sure maxUlps is non-negative and small enough that the // default NAN won't compare as equal to anything. assert(maxUlps > 0 && maxUlps < 4 * 1024 * 1024); int aInt = *(int*)&A; // Make aInt lexicographically ordered as a twos-complement int if (aInt < 0) aInt = 0x80000000 - aInt; // Make bInt lexicographically ordered as a twos-complement int int bInt = *(int*)&B; if (bInt < 0) bInt = 0x80000000 - bInt; int intDiff = abs(aInt - bInt); if (intDiff <= maxUlps) return true; return false; } 

सी ++ में एप्सिलॉन प्राप्त करने का पोर्टेबल तरीका है

 #include <limits> std::numeric_limits<double>::epsilon() 

तब तुलना फ़ंक्शन बन जाता है

 #include <cmath> #include <limits> bool AreSame(double a, double b) { return std::fabs(a - b) < std::numeric_limits<double>::epsilon(); } 

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

हम फ्लोटिंग-पॉइंट सहिष्णुता में थोड़ा और अधिक व्यावहारिक लेख देख सकते हैं और नोट्स है कि निरपेक्ष सहिष्णुता परीक्षण होता है, जो सी ++ में इस से उगलता है:

 bool absoluteToleranceCompare(double x, double y) { return std::fabs(x - y) <= std::numeric_limits<double>::epsilon() ; } 

और सापेक्ष सहिष्णुता परीक्षण:

 bool relativeToleranceCompare(double x, double y) { double maxXY = std::max( std::fabs(x) , std::fabs(y) ) ; return std::fabs(x - y) <= std::numeric_limits<double>::epsilon()*maxXY ; } 

लेख नोट करता है कि पूर्ण परीक्षण विफल हो जाता है जब x और y बड़े होते हैं और रिश्तेदार मामले में विफल होते हैं जब वे छोटे होते हैं मान लें कि वह निरपेक्ष और सापेक्ष सहिष्णुता यही है कि एक संयुक्त परीक्षण इस तरह दिखता है:

 bool combinedToleranceCompare(double x, double y) { double maxXYOne = std::max( { 1.0, std::fabs(x) , std::fabs(y) } ) ; return std::fabs(x - y) <= std::numeric_limits<double>::epsilon()*maxXYOne ; } 

आपके द्वारा लिखा गया कोड बगड़ा हुआ है:

 return (diff < EPSILON) && (-diff > EPSILON); 

सही कोड होगा:

 return (diff < EPSILON) && (diff > -EPSILON); 

(… और हाँ यह अलग है)

मुझे आश्चर्य है कि क्या फ़ैब्र्स आपको कुछ मामलों में आलसी मूल्यांकन नहीं खोएगा। मैं कहूंगा कि यह संकलक पर निर्भर करता है। आप दोनों को आज़मा सकते हैं। यदि वे औसत के बराबर हैं, तो फ़ैब्रिक के साथ कार्यान्वयन करें।

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

अंत में आप इस फ़ंक्शन को इनलाइन करके बेहतर परिणाम प्राप्त कर सकते हैं। यद्यपि ज्यादा सुधार की संभावना नहीं है …

संपादित करें: ओ जे, आपका कोड सुधारने के लिए धन्यवाद मैंने अपनी टिप्पणी को तदनुसार मिटा दिया

`वापसी फ़ैब्स (ए – बी) <एपिलॉन;

यह ठीक है अगर:

  • आपके निविष्टियों के परिमाण के क्रम ज्यादा नहीं बदलते हैं
  • बहुत कम संख्या में विपरीत संकेतों को समान माना जा सकता है

लेकिन अन्यथा यह आपको परेशानी में ले जाएगा डबल सटीक संख्याओं में लगभग 16 दशमलव स्थानों का संकल्प है। यदि आपके द्वारा तुलना की जा रही दो संख्याएं EPSILON * 1.0E16 की तुलना में बड़े हैं, तो आप ये भी कह सकते हैं:

 return a==b; 

मैं एक अलग दृष्टिकोण की जांच करता हूं जो मानता है कि आपको पहले अंक के बारे में चिंता करने की ज़रूरत है और दूसरी मान लीजिए आपका आवेदन ठीक है। एक समाधान कुछ ऐसा होगा:

 #define VERYSMALL (1.0E-150) #define EPSILON (1.0E-8) bool AreSame(double a, double b) { double absDiff = fabs(a - b); if (absDiff < VERYSMALL) { return true; } double maxAbs = max(fabs(a) - fabs(b)); return (absDiff/maxAbs) < EPSILON; } 

यह कम्प्यूटेशनल महंगा है, लेकिन कभी-कभी इसके लिए क्या कहा जाता है। यह हमारी कंपनी में क्या करना है क्योंकि हम इंजीनियरिंग लाइब्रेरी से निपटते हैं और आदानों के परिमाण के कुछ दर्जन आदेशों के अनुसार भिन्न हो सकते हैं।

वैसे भी, यह मुद्दा यह है (और व्यावहारिक रूप से हर प्रोग्रामिंग समस्या पर लागू होता है): अपनी आवश्यकताओं की जांच करें, फिर अपनी आवश्यकताओं को पूरा करने के लिए एक समाधान के साथ आओ – यह समझें कि आसान उत्तर आपकी आवश्यकताओं को पूरा करेगा। यदि आपके मूल्यांकन के बाद आपको पता चलता है कि fabs(ab) < EPSILON पर्याप्त होगा, इसका उपयोग करें – इसका उपयोग करें! लेकिन अपनी कमियों और अन्य संभावित समाधानों के बारे में भी जागरूक रहें

जैसा कि अन्य ने बताया है, एक निश्चित-एक्सपोनेंट एप्सिलॉन (जैसे 0.0000001) का इस्तेमाल करना मूल्यों के लिए एप्सिलॉन मूल्य से दूर बेकार होगा। उदाहरण के लिए, यदि आपके दो मान 10000.000 9 77 और 10000 हैं, तो इन दो अंकों के बीच कोई 32-बिट फ्लोटिंग-पॉइंट वैल्यू नहीं हैं – 10000 और 10000.000 977 उतने करीब हैं जितना आप बिट-टू-बिट समान के बिना प्राप्त कर सकते हैं। यहां, 0.000 9 से कम का एक एप्सिलॉन अर्थहीन है; आप सीधे समानता ऑपरेटर का इस्तेमाल कर सकते हैं

इसी प्रकार, जैसा कि दोनों मान आकार में एप्सिलॉन दृष्टिकोण करते हैं, रिश्तेदार त्रुटि 100% तक बढ़ जाती है।

इस प्रकार, फिक्स्ड पॉइंट वैल्यू (जहां एक्सपोनेंट मनमाना है) के साथ एक निश्चित बिंदु संख्या को मिलाकर 0.00001 जैसे मिश्रण करना एक व्यर्थ व्यायाम है यह केवल तभी काम करेगा यदि आप यह आश्वासन दिया जा सकता है कि परिचालित मूल्य एक संकीर्ण डोमेन (जो कि कुछ विशिष्ट एक्सपोनेंट के करीब है) में है, और यदि आप उस विशिष्ट परीक्षण के लिए एक एप्सिलॉन मान को ठीक से चुनते हैं यदि आप हवा से बाहर एक नंबर खींचते हैं ("अरे! 0.00001 छोटा है, तो यह अच्छा होगा!"), आप संख्यात्मक त्रुटियों के लिए बर्बाद हो रहे हैं मैंने कई बार बिग डिजिटल कोड डिबग कर रखा है, जहां कुछ खराब स्कमक यादृच्छिक एप्सिलॉन मूल्यों में टॉस करता है ताकि एक और टेस्ट केस का काम हो सके।

यदि आप किसी भी प्रकार की संख्यात्मक प्रोग्रामिंग करते हैं और विश्वास करते हैं कि आपको फिक्स्ड पॉइंट एपिसलन्स के लिए पहुंचने की आवश्यकता है, तो बोट्स के अनुच्छेद को फ़्लोटिंग-अंक संख्या से तुलना करें

फ़्लोटिंग प्वाइंट संख्या की तुलना करना

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

इस महान धागे में सामग्री के माध्यम से जाकर मैंने कुछ समय व्यतीत किया। मुझे संदेह है कि हर कोई इतना समय बिताना चाहता है, इसलिए मैं जो मैंने सीखा है और जो समाधान मैंने लागू किया है उसका सारांश हाइलाइट किया।

त्वरित सारांश

  1. फ्लोट की तुलना में दो समस्याएँ हैं: आपके पास सीमित सटीक और "लगभग शून्य" का अर्थ संदर्भ पर निर्भर करता है (अगला बिंदु देखें)।
  2. क्या 1E-8 लगभग 1 ई -16 के समान है? यदि आप शोर संवेदक डेटा देख रहे हैं तो शायद हां, लेकिन यदि आप आणविक सिमुलेशन कर रहे हैं तो हो सकता है! निचला रेखा: आपको विशिष्ट फ़ंक्शन कॉल के संदर्भ में हमेशा सहिष्णुता मान के बारे में सोचने की आवश्यकता होती है और इसे सामान्य ऐप-वाइड हार्ड-कोडित निरंतर भी नहीं बनाते
  3. सामान्य पुस्तकालय फ़ंक्शंस के लिए, यह अभी भी अच्छा है कि डिफ़ॉल्ट सहिष्णुता के साथ पैरामीटर हो। एक विशिष्ट पसंद संख्यात्मक _limits numeric_limits::epsilon() जो फ़्लैट एच में FLT_EPSILON के समान है। हालांकि यह समस्याग्रस्त है क्योंकि 1 ए 9 जैसी मूल्यों के लिए एपिसलोन के समान नहीं अगर 1.0 की तरह मूल्यों की तुलना करने के लिए एप्सिलॉन। FLT_EPSILON को 1.0 के लिए परिभाषित किया गया है।
  4. संख्या सहिष्णुता के भीतर है या नहीं यह स्पष्ट करने के लिए कार्यान्वयन है कि fabs(ab) <= epsilon हालांकि यह काम नहीं करता क्योंकि डिफ़ॉल्ट एपिसलोन को 1.0 के लिए परिभाषित किया गया है। ए और बी के संदर्भ में हमें एप्सिलॉन को ऊपर या नीचे बढ़ाया जाना चाहिए।
  5. There are two solution to this problem: either you set epsilon proportional to max(a,b) or you can get next representable numbers around a and then see if b falls into that range. The former is called "relative" method and later is called ULP method.
  6. Both methods actually fails anyway when comparing with 0. In this case, application must supply correct tolerance.

Utility Functions Implementation (C++11)

 //implements relative method - do not use for comparing with zero //use this most of the time, tolerance needs to be meaningful in your context template<typename TReal> static bool isApproximatelyEqual(TReal a, TReal b, TReal tolerance = std::numeric_limits<TReal>::epsilon()) { TReal diff = std::fabs(a - b); if (diff <= tolerance) return true; if (diff < std::fmax(std::fabs(a), std::fabs(b)) * tolerance) return true; return false; } //supply tolerance that is meaningful in your context //for example, default tolerance may not work if you are comparing double with float template<typename TReal> static bool isApproximatelyZero(TReal a, TReal tolerance = std::numeric_limits<TReal>::epsilon()) { if (std::fabs(a) <= tolerance) return true; return false; } //use this when you want to be on safe side //for example, don't start rover unless signal is above 1 template<typename TReal> static bool isDefinitelyLessThan(TReal a, TReal b, TReal tolerance = std::numeric_limits<TReal>::epsilon()) { TReal diff = a - b; if (diff < tolerance) return true; if (diff < std::fmax(std::fabs(a), std::fabs(b)) * tolerance) return true; return false; } template<typename TReal> static bool isDefinitelyGreaterThan(TReal a, TReal b, TReal tolerance = std::numeric_limits<TReal>::epsilon()) { TReal diff = a - b; if (diff > tolerance) return true; if (diff > std::fmax(std::fabs(a), std::fabs(b)) * tolerance) return true; return false; } //implements ULP method //use this when you are only concerned about floating point precision issue //for example, if you want to see if a is 1.0 by checking if its within //10 closest representable floating point numbers around 1.0. template<typename TReal> static bool isWithinPrecisionInterval(TReal a, TReal b, unsigned int interval_size = 1) { TReal min_a = a - (a - std::nextafter(a, std::numeric_limits<TReal>::lowest())) * interval_size; TReal max_a = a + (std::nextafter(a, std::numeric_limits<TReal>::max()) - a) * interval_size; return min_a <= b && max_a >= b; } 

Unfortunately, even your "wasteful" code is incorrect. EPSILON is the smallest value that could be added to 1.0 and change its value. The value 1.0 is very important — larger numbers do not change when added to EPSILON. Now, you can scale this value to the numbers you are comparing to tell whether they are different or not. The correct expression for comparing two doubles is:

 if (fabs(a - b) <= DBL_EPSILON * fmax(fabs(a), fabs(b))) { // ... } 

This is at a minimum. In general, though, you would want to account for noise in your calculations and ignore a few of the least significant bits, so a more realistic comparison would look like:

 if (fabs(a - b) <= 16 * DBL_EPSILON * fmax(fabs(a), fabs(b))) { // ... } 

If comparison performance is very important to you and you know the range of your values, then you should use fixed-point numbers instead.

My class based on previously posted answers. Very similar to Google's code but I use a bias which pushes all NaN values above 0xFF000000. That allows a faster check for NaN.

This code is meant to demonstrate the concept, not be a general solution. Google's code already shows how to compute all the platform specific values and I didn't want to duplicate all that. I've done limited testing on this code.

 typedef unsigned int U32; // Float Memory Bias (unsigned) // ----- ------ --------------- // NaN 0xFFFFFFFF 0xFF800001 // NaN 0xFF800001 0xFFFFFFFF // -Infinity 0xFF800000 0x00000000 --- // -3.40282e+038 0xFF7FFFFF 0x00000001 | // -1.40130e-045 0x80000001 0x7F7FFFFF | // -0.0 0x80000000 0x7F800000 |--- Valid <= 0xFF000000. // 0.0 0x00000000 0x7F800000 | NaN > 0xFF000000 // 1.40130e-045 0x00000001 0x7F800001 | // 3.40282e+038 0x7F7FFFFF 0xFEFFFFFF | // Infinity 0x7F800000 0xFF000000 --- // NaN 0x7F800001 0xFF000001 // NaN 0x7FFFFFFF 0xFF7FFFFF // // Either value of NaN returns false. // -Infinity and +Infinity are not "close". // -0 and +0 are equal. // class CompareFloat{ public: union{ float m_f32; U32 m_u32; }; static bool CompareFloat::IsClose( float A, float B, U32 unitsDelta = 4 ) { U32 a = CompareFloat::GetBiased( A ); U32 b = CompareFloat::GetBiased( B ); if ( (a > 0xFF000000) || (b > 0xFF000000) ) { return( false ); } return( (static_cast<U32>(abs( a - b ))) < unitsDelta ); } protected: static U32 CompareFloat::GetBiased( float f ) { U32 r = ((CompareFloat*)&f)->m_u32; if ( r & 0x80000000 ) { return( ~r - 0x007FFFFF ); } return( r + 0x7F800000 ); } }; 

I'd be very wary of any of these answers that involves floating point subtraction (eg, fabs(ab) < epsilon). First, the floating point numbers become more sparse at greater magnitudes and at high enough magnitudes where the spacing is greater than epsilon, you might as well just be doing a == b. Second, subtracting two very close floating point numbers (as these will tend to be, given that you're looking for near equality) is exactly how you get catastrophic cancellation .

While not portable, I think grom's answer does the best job of avoiding these issues.

There are actually cases in numerical software where you want to check whether two floating point numbers are exactly equal. I posted this on a similar question

https://stackoverflow.com/a/10973098/1447411

So you can not say that "CompareDoubles1" is wrong in general.

It depends on how precise you want the comparison to be. If you want to compare for exactly the same number, then just go with ==. (You almost never want to do this unless you actually want exactly the same number.) On any decent platform you can also do the following:

 diff= a - b; return fabs(diff)<EPSILON; 

as fabs tends to be pretty fast. By pretty fast I mean it is basically a bitwise AND, so it better be fast.

And integer tricks for comparing doubles and floats are nice but tend to make it more difficult for the various CPU pipelines to handle effectively. And it's definitely not faster on certain in-order architectures these days due to using the stack as a temporary storage area for values that are being used frequently. (Load-hit-store for those who care.)

In terms of the scale of quantities:

If epsilon is the small fraction of the magnitude of quantity (ie relative value) in some certain physical sense and A and B types is comparable in the same sense, than I think, that the following is quite correct:

 #include <limits> #include <iomanip> #include <iostream> #include <cmath> #include <cstdlib> #include <cassert> template< typename A, typename B > inline bool close_enough(A const & a, B const & b, typename std::common_type< A, B >::type const & epsilon) { using std::isless; assert(isless(0, epsilon)); // epsilon is a part of the whole quantity assert(isless(epsilon, 1)); using std::abs; auto const delta = abs(a - b); auto const x = abs(a); auto const y = abs(b); // comparable generally and |a - b| < eps * (|a| + |b|) / 2 return isless(epsilon * y, x) && isless(epsilon * x, y) && isless((delta + delta) / (x + y), epsilon); } int main() { std::cout << std::boolalpha << close_enough(0.9, 1.0, 0.1) << std::endl; std::cout << std::boolalpha << close_enough(1.0, 1.1, 0.1) << std::endl; std::cout << std::boolalpha << close_enough(1.1, 1.2, 0.01) << std::endl; std::cout << std::boolalpha << close_enough(1.0001, 1.0002, 0.01) << std::endl; std::cout << std::boolalpha << close_enough(1.0, 0.01, 0.1) << std::endl; return EXIT_SUCCESS; } 
 /// testing whether two doubles are almost equal. We consider two doubles /// equal if the difference is within the range [0, epsilon). /// /// epsilon: a positive number (supposed to be small) /// /// if either x or y is 0, then we are comparing the absolute difference to /// epsilon. /// if both x and y are non-zero, then we are comparing the relative difference /// to epsilon. bool almost_equal(double x, double y, double epsilon) { double diff = x - y; if (x != 0 && y != 0){ diff = diff/y; } if (diff < epsilon && -1.0*diff < epsilon){ return true; } return false; } 

I used this function for my small project and it works, but note the following:

Double precision error can create a surprise for you. Let's say epsilon = 1.0e-6, then 1.0 and 1.000001 should NOT be considered equal according to the above code, but on my machine the function considers them to be equal, this is because 1.000001 can not be precisely translated to a binary format, it is probably 1.0000009xxx. I test it with 1.0 and 1.0000011 and this time I get the expected result.

I use this code:

 bool AlmostEqual(double v1, double v2) { return (std::fabs(v1 - v2) < std::fabs(std::min(v1, v2)) * std::numeric_limits<double>::epsilon()); } 

I write this for java, but maybe you find it useful. It uses longs instead of doubles, but takes care of NaNs, subnormals, etc.

 public static boolean equal(double a, double b) { final long fm = 0xFFFFFFFFFFFFFL; // fraction mask final long sm = 0x8000000000000000L; // sign mask final long cm = 0x8000000000000L; // most significant decimal bit mask long c = Double.doubleToLongBits(a), d = Double.doubleToLongBits(b); int ea = (int) (c >> 52 & 2047), eb = (int) (d >> 52 & 2047); if (ea == 2047 && (c & fm) != 0 || eb == 2047 && (d & fm) != 0) return false; // NaN if (c == d) return true; // identical - fast check if (ea == 0 && eb == 0) return true; // ±0 or subnormals if ((c & sm) != (d & sm)) return false; // different signs if (abs(ea - eb) > 1) return false; // b > 2*a or a > 2*b d <<= 12; c <<= 12; if (ea < eb) c = c >> 1 | sm; else if (ea > eb) d = d >> 1 | sm; c -= d; return c < 65536 && c > -65536; // don't use abs(), because: // There is a posibility c=0x8000000000000000 which cannot be converted to positive } public static boolean zero(double a) { return (Double.doubleToLongBits(a) >> 52 & 2047) < 3; } 

Keep in mind that after a number of floating-point operations, number can be very different from what we expect. There is no code to fix that.

My way may not be correct but useful

Convert both float to strings and then do string compare

 bool IsFlaotEqual(float a, float b, int decimal) { TCHAR form[50] = _T(""); _stprintf(form, _T("%%.%df"), decimal); TCHAR a1[30] = _T(""), a2[30] = _T(""); _stprintf(a1, form, a); _stprintf(a2, form, b); if( _tcscmp(a1, a2) == 0 ) return true; return false; } 

operator overlaoding can also be done

You cannot compare two double with a fixed EPSILON . Depending on the value of double , EPSILON varies.

A better double comparison would be:

 bool same(double a, double b) { return std::nextafter(a, std::numeric_limits<double>::lowest()) <= b && std::nextafter(a, std::numeric_limits<double>::max()) >= b; } 

In a more generic way:

 template <typename T> bool compareNumber(const T& a, const T& b) { return std::abs(a - b) < std::numeric_limits<T>::epsilon(); } 

Why not perform bitwise XOR? Two floating point numbers are equal if their corresponding bits are equal. I think, the decision to place the exponent bits before mantissa was made to speed up comparison of two floats. I think, many answers here are missing the point of epsilon comparison. Epsilon value only depends on to what precision floating point numbers are compared. For example, after doing some arithmetic with floats you get two numbers: 2.5642943554342 and 2.5642943554345. They are not equal, but for the solution only 3 decimal digits matter so then they are equal: 2.564 and 2.564. In this case you choose epsilon equal to 0.001. Epsilon comparison is also possible with bitwise XOR. Correct me if I am wrong.