c++ - উনল - সি++ বই




ভাসা এবং ডবল তুলনা জন্য সবচেয়ে কার্যকর উপায় কি? (18)

দুটি 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);
}

প্রক্রিয়াজাতকরণ বর্জ্য মনে হয়।

কেউ কি একটি স্মার্ট ফ্লাট তুলনাকারী জানেন?


`ফেরত fabs (একটি - বি) <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 যথেষ্ট হবে, নিখুঁত - এটি ব্যবহার করুন! কিন্তু তার ক্ষয়ক্ষতি এবং অন্যান্য সম্ভাব্য সমাধান সম্পর্কে সচেতন থাকুন।


C ++ এ epsilon পেতে পোর্টেবল উপায়

#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();
}

আপনার লেখা কোডটি বাগ হয়েছে:

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

সঠিক কোড হবে:

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

(... এবং হ্যাঁ এই ভিন্ন)

Fabs আপনি কিছু ক্ষেত্রে অলস মূল্যায়ন হারাতে হবে না যদি আমি আশ্চর্য। আমি এটা কম্পাইলার উপর নির্ভর করবে বলে। আপনি উভয় চেষ্টা করতে পারেন। তারা গড় সমতুল্য, fabs সঙ্গে বাস্তবায়ন নিতে।

যদি আপনার দুটি তথ্য কোনটি দুটি ফ্ল্যাটের চেয়ে বড় হতে পারে তার কিছু তথ্য থাকে তবে অলস মূল্যায়নে আরও ভাল সুবিধা নেওয়ার তুলনায় আপনি তুলনা করতে পারেন।

অবশেষে আপনি এই ফাংশন inlining দ্বারা ভাল ফলাফল পেতে পারে। যদিও অনেক উন্নত করার সম্ভাবনা নেই ...

সম্পাদনা করুন: ওজে, আপনার কোড সংশোধন করার জন্য ধন্যবাদ। আমি সেই অনুযায়ী আমার মন্তব্য মুছে ফেলা


আমি এই মহান থ্রেড উপাদান মাধ্যমে যাচ্ছে বেশ কিছু সময় শেষ পর্যন্ত শেষ। আমি সবার জন্য এত সময় ব্যয় করতে চাই, তাই আমি যা শিখেছি এবং আমি যে সমাধানটি বাস্তবায়ন করেছি তার সারাংশ হাইলাইট করব।

দ্রুত সারসংক্ষেপ

  1. ফ্লোট তুলনা করে দুটি সমস্যা রয়েছে: আপনার কাছে সীমিত স্পষ্টতা এবং "আনুমানিক শূন্য" মানে অর্থ প্রসঙ্গে (পরবর্তী বিন্দুটি দেখুন) নির্ভর করে।
  2. 1E-8 প্রায় 1E-16 হিসাবে একই? আপনি যদি গোলমাল সেন্সর তথ্য খুঁজছেন হয় তাহলে সম্ভবত হ্যাঁ কিন্তু যদি আপনি আণবিক সিমুলেশন করছেন তাহলে হতে পারে না! নিচের লাইন: আপনি সবসময় নির্দিষ্ট ফাংশন কল প্রসঙ্গে সহনশীলতা মান সম্পর্কে চিন্তা করতে হবে এবং এটি কেবল জেনেরিক অ্যাপ-ওয়াইড হার্ড-কোডেড ধ্রুবক নয়।
  3. সাধারন লাইব্রেরি ফাংশনগুলির জন্য, ডিফল্ট সহনশীলতার সাথে পরামিতি থাকা এখনও ভাল। একটি সাধারণ পছন্দটি numeric_limits::epsilon() যা float.h এ FLT_EPSILON হিসাবে একই। তবে এটি সমস্যাযুক্ত কারণ Epsilon 1.0 এর মতো মানগুলির তুলনা করার জন্য যদি epsilon হিসাবে 1E9 এর মতো মানগুলির জন্য নয়। FLT_EPSILON 1.0 এর জন্য সংজ্ঞায়িত করা হয়।
  4. সংখ্যা সহনশীলতার মধ্যে কিনা তা যাচাই করার সুস্পষ্ট বাস্তবায়ন হল fabs(ab) <= epsilon তবে এটি কাজ করে না কারণ ডিফল্ট ইস্পিলন 1.0 এর জন্য সংজ্ঞায়িত করা হয়। আমরা A এবং B পদে আপসিলন আপ বা ডাউন স্কেল করতে হবে।
  5. এই সমস্যার দুটি সমাধান রয়েছে: আপনি max(a,b) অনুপাতযুক্ত ইপিসিলন সেট করুন অথবা আপনি পরবর্তী চারটি প্রতিনিধিত্বযোগ্য সংখ্যা পেতে পারেন এবং তারপরে দেখেন যে বিটি সেই সীমার মধ্যে পড়ে কিনা। প্রাক্তনটিকে "আপেক্ষিক" পদ্ধতি বলা হয় এবং পরে ULP পদ্ধতি বলা হয়।
  6. উভয় পদ্ধতি আসলে 0 সঙ্গে তুলনা করে যাইহোক ব্যর্থ হয়। এই ক্ষেত্রে, অ্যাপ্লিকেশন সঠিক সহনশীলতা সরবরাহ করতে হবে।

ইউটিলিটি ফাংশন বাস্তবায়ন (সি ++ 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;
}

একটি epsilon মান সঙ্গে তুলনা অধিকাংশ মানুষ কি (এমনকি গেম প্রোগ্রামিং)।

আপনি আপনার বাস্তবায়ন একটু পরিবর্তন করা উচিত যদিও:

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

সম্পাদনা: Christer একটি সাম্প্রতিক ব্লগ পোস্টে এই বিষয়ে দুর্দান্ত তথ্যের একটি স্ট্যাক যোগ করেছেন। উপভোগ করুন।


এটি বুঝতে একটি পুরানো থ্রেড তবে এই প্রবন্ধটি আমি ভাসমান বিন্দু সংখ্যার তুলনায় সর্বাধিক সোজা অগ্রগতিগুলির মধ্যে একটি এবং যদি আপনি আরো অন্বেষণ করতে চান তবে এটিতে আরও বিশদ উল্লেখ রয়েছে এবং এটি মূল বিষয়গুলির সম্পূর্ণ পরিসরকে অন্তর্ভুক্ত করে ভাসমান বিন্দু সংখ্যা সঙ্গে ডিল Floating- পয়েন্ট গাইড: তুলনা

আমরা পর্যায়ক্রমে ভাসমান-বিন্দু সহনশীলতাগুলির মধ্যে কিছুটা আরও বেশি ব্যবহারিক নিবন্ধ খুঁজে পেতে পারি এবং নিখরচায় সহনশীলতা পরীক্ষাটি রয়েছে যা সি ++ এ এটিকে উড়ে যায়:

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 ;
}

প্রস্থ উপর নির্ভর করে ভাসমান বিন্দু সংখ্যা তুলনা। যেহেতু অপারেশনগুলির ক্রম পরিবর্তন করার ফলে বিভিন্ন ফলাফল উত্পন্ন হতে পারে, তা জানতে হবে যে সংখ্যাগুলি কত "সমান" আপনি চান।

ভাসমান বিন্দু তুলনা করার সময় ব্রুস ডসন দ্বারা ভাসমান বিন্দু সংখ্যা তুলনা একটি ভাল জায়গা।

নিম্নলিখিত সংজ্ঞাগুলি নুথের কম্পিউটার প্রোগ্রামিং শিল্প থেকে এসেছে:

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);
}

অবশ্যই, epsilon নির্বাচন প্রসঙ্গে নির্ভর করে, এবং সংখ্যার কতগুলি সমান হতে চান তা নির্ধারণ করে।

ভলিউটিং পয়েন্ট সংখ্যা তুলনা করার আরেকটি পদ্ধতি হল নম্বরগুলির ইউএলপি (শেষ স্থানে ইউনিট) দেখতে। যদিও তুলনামূলকভাবে বিশেষভাবে আচরণ না করে , কাগজটি কীভাবে ভলিউটিং পয়েন্ট সংখ্যাগুলি সম্পর্কে জানার উচিত তা হল কীভাবে ভলিউটিং বিন্দু কাজ করে এবং কী সমস্যাগুলি বোঝার জন্য একটি ভাল সম্পদ, যা ULP এর অন্তর্ভুক্ত।


Qt দুটি ফাংশন প্রয়োগ করে, আপনি তাদের কাছ থেকে শিখতে পারেন:

static inline bool qFuzzyCompare(double p1, double p2)
{
    return (qAbs(p1 - p2) <= 0.000000000001 * qMin(qAbs(p1), qAbs(p2)));
}

static inline bool qFuzzyCompare(float p1, float p2)
{
    return (qAbs(p1 - p2) <= 0.00001f * qMin(qAbs(p1), qAbs(p2)));
}

এবং আপনি নিম্নলিখিত ফাংশন প্রয়োজন হতে পারে, যেহেতু

উল্লেখ্য যে মানগুলি তুলনা করা যেখানে প1 বা পি 2 হয় 0.0 কাজ করবে না, না মূল্যগুলির তুলনা করবে যেখানে মানগুলির মধ্যে একটি মান NaN বা অনন্ত। মানগুলির মধ্যে একটিতে সর্বদা 0.0 থাকলে, পরিবর্তে qFuzzyIsNull ব্যবহার করুন। যদি মানের মধ্যে একটি 0.0 হতে পারে, একটি সমাধান উভয় মান 1.0 যোগ করতে হয়।

static inline bool qFuzzyIsNull(double d)
{
    return qAbs(d) <= 0.000000000001;
}

static inline bool qFuzzyIsNull(float f)
{
    return qAbs(f) <= 0.00001f;
}

আমি এই কোড ব্যবহার করি:

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

আরও সাধারণ ভাবে:

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

অন্যরা যেমন উল্লেখ করেছে, নির্দিষ্ট সংখ্যার ইপিসিলন (যেমন 0.0000001) ব্যবহার করে অ্যাপসিলন মান থেকে দূরে থাকা মূল্যের জন্য নিরর্থক হবে । উদাহরণস্বরূপ, যদি আপনার দুইটি মান 10000.000977 এবং 10000 হয়, তাহলে এই দুটি সংখ্যাগুলির মধ্যে কোন 32-বিট ভাসমান-বিন্দু মান নেই - 10000 এবং 10000.000977 আপনি যতটা সম্ভব বিট-বিট অভিন্ন ছাড়াও পেতে পারেন। এখানে, 0.0009 এর চেয়ে কম একটি epsilon অর্থহীন; আপনি ভাল সমানতা অপারেটর ব্যবহার করতে পারে।

একইভাবে, দুটি মান আকারে ইপিসিলন পদ্ধতির সাথে সম্পর্কিত, আপেক্ষিক ত্রুটি 100% বৃদ্ধি পায়।

সুতরাং, 0.00001 হিসাবে একটি নির্দিষ্ট বিন্দু সংখ্যা ভাসমান করার চেষ্টা করছে ভাসমান-বিন্দু মানগুলির সাথে (যেখানে সূচকটি নির্বিচারে হয়) একটি বিন্দুহীন ব্যায়াম। এটি কেবল তখনই কাজ করবে যদি আপনি আশ্বস্ত হতে পারেন যে অপারেড মানগুলি একটি সংকীর্ণ ডোমেনে (অর্থাৎ, কিছু নির্দিষ্ট এক্সপোনের কাছে) মধ্যে থাকে এবং আপনি যদি সেই নির্দিষ্ট পরীক্ষার জন্য সঠিকভাবে একটি অ্যাপসিলন মান নির্বাচন করেন। যদি আপনি বায়ু থেকে একটি নম্বর টেনে আনেন ("আরে! 0.00001 ছোট, তাই এটি ভাল হতে হবে!"), আপনি সংখ্যাসূচক ত্রুটিগুলির জন্য নষ্ট হয়েছেন। আমি খারাপ সংখ্যাসূচক কোড ডিবাগ করার সময় অতিবাহিত করেছি যেখানে কিছু দরিদ্র schmuck এখনও অন্য পরীক্ষা ক্ষেত্রে কাজ করতে র্যান্ডম অ্যাপসিলন মানের মধ্যে টসে।

যদি আপনি কোন ধরনের সংখ্যাসূচক প্রোগ্রামিং করেন এবং বিশ্বাস করেন যে আপনি নির্দিষ্ট বিন্দু অ্যাপসিলনগুলির জন্য পৌঁছাতে চান তবে ফ্লোটিং পয়েন্ট সংখ্যা তুলনায় ব্রুসের নিবন্ধটি পড়ুন

ভাসমান পয়েন্ট সংখ্যা তুলনা


আপনি doubleএকটি নির্দিষ্ট সঙ্গে দুই তুলনা করতে পারবেন না EPSILON। মান উপর নির্ভর করে double, EPSILONপরিবর্তিত হয়।

একটি ভাল ডবল তুলনা হবে:

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;
}

আমি এই উত্তরগুলির যে কোনও ভাসমান বিন্দু বিয়োগ অন্তর্ভুক্ত (যেমন, fabs (ab) <epsilon) থেকে খুব সতর্ক থাকবো। প্রথমত, ভাসমান বিন্দু সংখ্যা বৃহত্তর পরিমাপে আরও স্পার্ক হয়ে ও উচ্চ পর্যাপ্ত পরিমাপে যেখানে স্পেসিং ইপিসিলন থেকে বড় হয়, আপনিও ঠিক একটি == বি করতে পারেন। দ্বিতীয়ত, দুটি খুব ঘনিষ্ঠ ভাসমান বিন্দু সংখ্যার বিয়োগ করা (যেহেতু এটিগুলি আপনাকে বলে দেবে যে আপনি সমান সমানতা খুঁজছেন) আপনি ঠিক বিপর্যয়মূলক বাতিলকরণ কীভাবে করবেন ।

পোর্টেবল না হলেও, আমি মনে করি গ্রোমের উত্তরগুলি এই সমস্যাগুলি এড়িয়ে চলার সর্বোত্তম কাজ করে।


আমি জাভা জন্য এই লিখুন, কিন্তু আপনি এটি দরকারী খুঁজে পেতে পারেন। এটি দ্বিগুণের পরিবর্তে লম্বা ব্যবহার করে, তবে NaNs, subnormals ইত্যাদি যত্ন নেয়।

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; }

মনে রাখবেন যে বেশিরভাগ ভাসমান-বিন্দু ক্রিয়াকলাপের পরে, আমরা যা আশা করি তার থেকে সংখ্যাটি ভিন্ন হতে পারে। যে ঠিক করার জন্য কোন কোড আছে।


এখানে প্রমাণটি ব্যবহার std::numeric_limits::epsilon()করা উত্তর নয় - এটি একের চেয়ে বেশি মানগুলির জন্য ব্যর্থ হয়:

উপরে আমার মন্তব্য প্রমাণ:

#include <stdio.h>
#include <limits>

double ItoD (__int64 x) {
    // Return double from 64-bit hexadecimal representation.
    return *(reinterpret_cast<double*>(&x));
}

void test (__int64 ai, __int64 bi) {
    double a = ItoD(ai), b = ItoD(bi);
    bool close = std::fabs(a-b) < std::numeric_limits<double>::epsilon();
    printf ("%.16f and %.16f %s close.\n", a, b, close ? "are " : "are not");
}

int main()
{
    test (0x3fe0000000000000L,
          0x3fe0000000000001L);

    test (0x3ff0000000000000L,
          0x3ff0000000000001L);
}

চলমান এই আউটপুট ফলন:

0.5000000000000000 and 0.5000000000000001 are  close.
1.0000000000000000 and 1.0000000000000002 are not close.

নোট করুন যে দ্বিতীয় ক্ষেত্রে (এক এবং একের চেয়ে বড়), দুটি ইনপুট মানগুলি সম্ভবত যতটা সম্ভব সেগুলির কাছাকাছি, এবং এখনও ঘনিষ্ঠ হিসাবে তুলনা করে। সুতরাং, 1.0 এর চেয়েও বেশি মানগুলির জন্য, আপনি কেবলমাত্র সমতা পরীক্ষাটি ব্যবহার করতে পারেন। ভাসমান-বিন্দু মান তুলনা করার সময় স্থায়ী epsilons আপনাকে সংরক্ষণ করবে না।


এটা আপনি তুলনা করতে চান কিভাবে সুনির্দিষ্ট উপর নির্ভর করে। আপনি যদি ঠিক একই নম্বরের জন্য তুলনা করতে চান, তবে শুধু == দিয়ে যান। (যদি আপনি প্রকৃতপক্ষে একই নম্বরটি না চান তবে আপনি প্রায় এটি করতে চান না।) কোনও উপযুক্ত প্ল্যাটফর্মে আপনি নিম্নলিখিতগুলিও করতে পারেন:

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

হিসাবে fabsবেশ দ্রুত হতে থাকে। বেশ দ্রুত দ্বারা আমি বলতে চাচ্ছি এটি মূলত একটি বিটwise এবং তাই এটি দ্রুততর হবে।

এবং দ্বিগুণ এবং ভাসমান তুলনা করার জন্য পূর্ণসংখ্যা কৌশলগুলি চমৎকার তবে বিভিন্ন CPU পাইপলাইনগুলিকে কার্যকরীভাবে পরিচালনা করার জন্য এটি আরও কঠিন করে তোলে। এবং স্থিরভাবে ব্যবহৃত মানগুলির জন্য একটি অস্থায়ী সঞ্চয়স্থান হিসাবে স্ট্যাকগুলি ব্যবহার করার কারণে আজকাল নির্দিষ্ট কিছু ইন আর্কিটেকচারগুলিতে এটি দ্রুততর নয়। (যারা যত্ন জন্য লোড হিট দোকান।)


দুর্ভাগ্যবশত, এমনকি আপনার "বর্জ্যপূর্ণ" কোডটি ভুল। Epsilon হল ছোটতম মান যা 1.0 যোগ করা যেতে পারে এবং এর মান পরিবর্তন করতে পারে । মান 1.0 অত্যন্ত গুরুত্বপূর্ণ - EPSILON এ যোগ করা হলে বড় সংখ্যাগুলি পরিবর্তন হয় না। এখন, আপনি এই মানটিকে আপনি যে সংখ্যাগুলির সাথে তুলনা করছেন তা বলতে পারেন যে তারা ভিন্ন কিনা বা না। দুটি ডাবল তুলনা করার জন্য সঠিক অভিব্যক্তি হল:

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

এটি একটি সর্বনিম্ন। সাধারণভাবে, যদিও আপনি আপনার গণনার মধ্যে গোলমালের জন্য হিসাব করতে চান এবং কমপক্ষে উল্লেখযোগ্য কিছু বিটকে উপেক্ষা করতে চান, তাই আরো বাস্তববাদী তুলনাটি দেখতে হবে:

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

যদি তুলনামূলক পারফরম্যান্স আপনার কাছে খুবই গুরুত্বপূর্ণ এবং আপনি আপনার মানগুলির পরিধি জানেন তবে তার পরিবর্তে আপনাকে নির্দিষ্ট-বিন্দু সংখ্যার ব্যবহার করা উচিত।


ভাসমান বিন্দু সংখ্যার সাধারণ উদ্দেশ্য তুলনা সাধারণত অর্থহীন। তুলনা কিভাবে সত্যিই হাতে একটি সমস্যা উপর নির্ভর করে। অনেক সমস্যার মধ্যে, সংখ্যাগুলি প্রদত্ত সহনশীলতার মধ্যে তাদের তুলনা করার জন্য পর্যাপ্তরূপে বিযুক্ত করা হয়। দুর্ভাগ্যবশত, অনেক সমস্যা আছে, যেখানে এমন কৌশল সত্যিই কাজ করে না। এক উদাহরণের জন্য, আপনার পর্যবেক্ষণগুলি বাধাটির খুব কাছাকাছি হলে প্রশ্নগুলির একটি সংখ্যা (ডিজিটাল স্টক বিকল্পগুলি মনে রাখবেন) একটি হেভিসাইড (ধাপ) ফাংশনের সাথে কাজ করার কথা বিবেচনা করুন। সহনশীলতার উপর ভিত্তি করে তুলনা করা তুলনামূলকভাবে ভাল কাজ করবে না, কারণ এটি কার্যকরভাবে মূল বাধা থেকে দুটি নতুন অবস্থানে স্থানান্তরিত করবে। আবার, এ ধরনের সমস্যার জন্য কোনও সাধারণ উদ্দেশ্য সমাধান নেই এবং স্থিরতা অর্জনের জন্য নির্দিষ্ট সমাধানটির সংখ্যাসূচক পদ্ধতি পরিবর্তন করার প্রয়োজন হতে পারে।





floating-point