কোনও সিস্টেমের তুলনা করার সঠিক উপায় '' 0 '(দ্বিগুণ, কোন?)


87

দুঃখিত, এটি একটি সহজ বোকা প্রশ্ন হতে পারে, তবে আমার নিশ্চিত হওয়া দরকার know

আমার এই ifঅভিব্যক্তি আছে,

void Foo()
{
    System.Double something = GetSomething();
    if (something == 0) //Comparison of floating point numbers with equality 
                     // operator. Possible loss of precision while rounding value
        {}
}

যে অভিব্যক্তি সমান?

void Foo()
{
    System.Double something = GetSomething();
    if (something < 1)
        {}
}

? কারণ তখন আমার একটি সমস্যা হতে পারে, ifউদাহরণস্বরূপ 0.9 এর মান দিয়ে প্রবেশ করানো ।


4
// Comparison of floating point numbers with equality // operator. আপনার কি সত্যিই এটি নির্দিষ্ট করার দরকার ছিল? :)
জর্জ জনস্টন

4
হেক নং 0 এবং 1 এর মধ্যে অনেকগুলি মানের একটি নরক রয়েছে কেন এটি কেবল পরীক্ষা করে দেখুন না কেন?
ইগবি লার্জম্যান

12
আমার ফোকাসটি কোথায় তা দেখানোর জন্য আমি কেবল রেশার্পার মতোই লিখেছিলাম।
রেডবিএক্স

@ চারেলস: এছাড়াও, প্রচুর সংখ্যা রয়েছে যা 0 এর চেয়ে কম
ব্রায়ান

উত্তর:


116

ঠিক আছে, 0 এর সাথে মানটির কতটা কাছাকাছি দরকার? যদি আপনি প্রচুর ভাসমান পয়েন্ট অপারেশনগুলির মধ্য দিয়ে যান যা "অসীম নির্ভুলতা" এর ফলে 0 হতে পারে, আপনি 0 এর খুব কাছাকাছি ফলাফল দিয়ে শেষ করতে পারেন।

সাধারণত এই পরিস্থিতিতে আপনি কিছু ধরণের অ্যাপসিলন সরবরাহ করতে চান এবং ফলাফলটি ঠিক সেই এপসিলনের মধ্যেই রয়েছে তা পরীক্ষা করে দেখুন:

if (Math.Abs(something) < 0.001)

আপনার অ্যাপসিলনটি ব্যবহার করা উচিত অ্যাপ্লিকেশন-নির্দিষ্ট - এটি আপনি কী করছেন তার উপর নির্ভর করে।

অবশ্যই, ফলাফলটি যদি ঠিক শূন্য হয় তবে একটি সাধারণ সমতা পরীক্ষা করা ভাল।


আসলে, আমার একেবারে শূন্য হওয়া দরকার, কেমন দেখাচ্ছে? আমি ডাবল জিরো খুঁজলাম, তবে ভাগ্য জানি। একটি ধ্রুবক অধিকার আছে? বিটিডব্লিউ, ধন্যবাদ, আমি এখন
এপসিলনের

24
@ অ্যাডবিক্স: শুধু ব্যবহার করুন == 0। আপনি সেখানে একটি আক্ষরিক পেয়েছেন - এটি বেশ ধ্রুবক :)
জন স্কিটি

35

যদি somethingঅন্য কোনও অপারেশনের ফলাফল থেকে নির্ধারিত হয়ে থাকে something = 0তবে আপনি আরও ভাল ব্যবহার করতে পারেন:

if(Math.Abs(something) < Double.Epsilon)
{
//do something
}

সম্পাদনা করুন : এই কোডটি ভুল। অ্যাপসিলন ক্ষুদ্রতম সংখ্যা, তবে পুরো শূন্য নয়। আপনি যখন কোনও সংখ্যাকে অন্য সংখ্যার সাথে তুলনা করতে চান, তখন আপনাকে ভাবতে হবে যে গ্রহণযোগ্য সহনশীলতা কী। আসুন এটি বলা যাক .00001 এর বাইরে আপনার কোনও যত্ন নেই। এটিই আপনি ব্যবহার করবেন। মান ডোমেনের উপর নির্ভর করে। তবে এটি বেশিরভাগ ক্ষেত্রে অবশ্যই কখনও দ্বিগুণ হয় না ps


4
এই rounding সমস্যা সমাধানের নয়, উদাহরণস্বরূপ Math.Abs(0.1f - 0.1d) < double.Epsilonহয়false
টমাস লুলে

6
ডাবল।এপসিলন এ জাতীয় তুলনা করার জন্য খুব ছোট। ডাবল।এপসিলন হ'ল ক্ষুদ্রতম ধনাত্মক সংখ্যা যা ডাবল প্রতিনিধিত্ব করতে পারে।
এভেজেনি নবোকভ

4
এটি কোনও
অর্থবোধ করে

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

4
@ মৌরজি: আপনারা ভুল: double d = Math.Sqrt(10100)*2; double a = Math.Sqrt(40400); if(Math.Abs(a - d) < double.Epsilon) { Console.WriteLine("true"); }
সোনাতিক

27

আপনার somethingএকটি doubleএবং আপনি লাইনে সঠিকভাবে চিহ্নিত করেছেন

if (something == 0)

আমাদের একটি doubleবাম দিকে (lhs) এবং একটি intডানদিকে (rhs) আছে।

তবে এখন মনে হচ্ছে আপনি ভাবেন যে lhs একটিতে রূপান্তরিত হবে int, এবং তারপরে ==চিহ্নটি দুটি পূর্ণসংখ্যার সাথে তুলনা করবে। যা হয় তাই না । রূপান্তর থেকে double থেকে int হয় স্পষ্ট এবং "স্বয়ংক্রিয়ভাবে" ঘটতে করতে পারবে না।

পরিবর্তে, বিপরীত ঘটে। আরএইচএস রূপান্তরিত হয় doubleএবং তারপরে ==সাইনটি দুটি ডাবলের মধ্যে সমতা পরীক্ষায় পরিণত হয়। এই রূপান্তর অন্তর্নিহিত (স্বয়ংক্রিয়)।

এটি লিখতে ভাল (কিছু দ্বারা) বিবেচনা করা হয়

if (something == 0.0)

বা

if (something == 0d)

কারণ তখনই তাড়াতাড়ি আপনি দুটি ডাবল তুলনা করছেন। তবে, এটি কেবল স্টাইল এবং পঠনযোগ্যতার বিষয় কারণ সংকলক যে কোনও ক্ষেত্রে একই কাজ করবে।

কিছু ক্ষেত্রে জোন স্কিটের উত্তরের মতো "সহনশীলতা" প্রবর্তন করাও এটি প্রাসঙ্গিক, তবে সেই সহনশীলতাও doubleঅনেকটা হবে। এটা তোলে পারে অবশ্যই হতে 1.0যদি আপনি চেয়েছিলেন, কিন্তু এটা হতে হবে না [অন্তত কঠোরভাবে ইতিবাচক] পূর্ণসংখ্যা।


17

আপনি যদি কেবল সতর্কতা দমন করতে চান তবে এটি করুন:

if (something.Equals(0.0))

অবশ্যই, এটি কেবলমাত্র একটি বৈধ সমাধান যদি আপনি জানেন যে প্রবাহটি কোনও উদ্বেগ নয়। আমি প্রায়শই শূন্য দ্বারা ভাগ করতে যাচ্ছি কিনা তা পরীক্ষা করতে এটি করি do


4

আমি মনে করি না এটা সমান, সত্য বলে। আপনার নিজের উদাহরণ বিবেচনা করুন: কিছু = 0.9 বা 0.0004। প্রথম ক্ষেত্রে এটি মিথ্যা হবে, দ্বিতীয় ক্ষেত্রে এটি সত্য হবে। এই ধরণের সাথে কাজ করার জন্য আমি সাধারণত আমার জন্য নির্ভুলতা শতাংশ নির্ধারণ করি এবং সেই নির্ভুলতার মধ্যে তুলনা করি। আপনার প্রয়োজনের উপর নির্ভর করে। কিছুটা এইরকম...

if(((int)(something*100)) == 0) {


//do something
}

আশাকরি এটা সাহায্য করবে.


4
কিছু ঠিক শূন্য হতে হবে।
র‌্যাডবিক্স

সুতরাং আপনি ভাগ্যবান লোক, এই ক্ষেত্রে :)
টিগ্রান

3

সমস্যাটি উপস্থাপনের উদাহরণ এখানে দেওয়া হয়েছে (লিনকিউপ্যাডে প্রস্তুত - আপনার যদি এটি কেবল পদ্ধতির Console.Writelineপরিবর্তে ব্যবহার না করা হয় Dump):

void Main()
{
    double x = 0.000001 / 0.1;
    double y = 0.001 * 0.01; 

    double res = (x-y);
    res.Dump();
    (res == 0).Dump();
}

উভয় x এবং y তাত্ত্বিকভাবে একই এবং সমান: 0.00001 তবে "অসীম নির্ভুলতা" না থাকার কারণে এই মানগুলি কিছুটা আলাদা। falseস্বাভাবিক উপায়ে 0 এর সাথে তুলনা করার সময় দুর্ভাগ্যক্রমে কিছুটা হলেও ফিরে আসতে পারে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.