জাভাতে ভাসমান তুলনা করতে == ব্যবহার করে কী হয়েছে?


177

এই জাভা.সুন পৃষ্ঠা অনুসারে ==জাভাতে ভাসমান পয়েন্ট সংখ্যাগুলির জন্য সমতা তুলনা অপারেটর।

তবে, আমি এই কোডটি টাইপ করার সময়:

if(sectionID == currentSectionID)

আমার সম্পাদক হিসাবে এবং স্থিতিশীল বিশ্লেষণ চালানো, আমি পেতে: "JAVA0078 ভাসমান পয়েন্ট মান ==" তুলনায়

==ভাসমান পয়েন্টের মানগুলির তুলনা করতে কী ভুল ? এটি করার সঠিক উপায় কী? 


29
যেহেতু ফ্লোটের সাথে == তুলনা করা সমস্যাযুক্ত তাই এগুলি আইডি হিসাবে ব্যবহার করা বুদ্ধিমানের নয়; আপনার উদাহরণ কোডের নামগুলি আপনাকে যা করছে তা বোঝায়; দীর্ঘ পূর্ণসংখ্যার (দীর্ঘ) অগ্রাধিকার দেওয়া হয়, এবং আইডিগুলির জন্য ডি-ফ্যাক্টো স্ট্যান্ডার্ড।
কার্ল ম্যানাস্টার


4
হ্যাঁ, এটি কি কেবল একটি এলোমেলো উদাহরণ বা আপনি আসলে আইডি হিসাবে ভাসা ব্যবহার করেন? কোন কারণ আছে?
প্রতি উইকল্যান্ডের

5
"ফ্লোট ফিল্ডগুলির জন্য, ফ্লোট ডটকম স্প্যার পদ্ধতিটি ব্যবহার করুন; এবং দ্বিগুণ ক্ষেত্রের জন্য ডাবল ডটকম স্প্যার ব্যবহার করুন at বিশদ জন্য ফ্লোট.একভ্যালস ডকুমেন্টেশন দেখুন। " (জোশুয়া ব্লচ: কার্যকর জাভা)
lbalazscs

উত্তর:


211

'সমতা' জন্য ভাসমান পরীক্ষা করার সঠিক উপায় হ'ল:

if(Math.abs(sectionID - currentSectionID) < epsilon)

যেখানে অ্যাপসিলন হ'ল 0.00000001 এর মতো খুব ছোট একটি সংখ্যা, পছন্দসই নির্ভুলতার উপর নির্ভর করে।


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

1
@ পিটি সে কি এক নম্বর দিয়ে অ্যাপসিলনকে গুণ করতে পারে এবং if(Math.abs(sectionID - currentSectionID) < epsilon*sectionIDএই সমস্যাটি মোকাবেলায় ফাংশন পরিবর্তন করতে পারে?
উত্সাহী লোক

3
এটি এখনও পর্যন্ত সেরা উত্তর হতে পারে, তবে এটি এখনও ত্রুটিযুক্ত। আপনি কোথা থেকে এপসিলন পাবেন?
মাইকেল পিফেল

1
@ মিশেলপিফেল এটি ইতিমধ্যে বলেছে: "পছন্দসই নির্ভুলতার উপর নির্ভর করে"। তাদের প্রকৃতি অনুসারে ভাসমানগুলি এক ধরণের শারীরিক মানগুলির মতো: আপনি কেবল মোট অসতীতার উপর নির্ভর করে কিছু সীমিত সংখ্যক অবস্থানের পক্ষে আগ্রহী, এর বাইরে যে কোনও পার্থক্যকে মোট হিসাবে বিবেচনা করা হয়।
ivan_pozdeev

তবে ওপি সত্যই কেবল সাম্যের জন্য পরীক্ষা করতে চেয়েছিল এবং যেহেতু এটি অবিশ্বাস্য হিসাবে পরিচিত, তাই আলাদা পদ্ধতি ব্যবহার করতে হবে। তবুও, আমি জানি না যে তিনি তার "পছন্দসই নির্ভুলতা" এমনকি কী জানেন; সুতরাং যদি আপনি যা চান তা আরও নির্ভরযোগ্য সমতা পরীক্ষা, প্রশ্ন থেকে যায়: আপনি কোথা থেকে এপসিলন পাবেন? আমি Math.ulp()এই প্রশ্নের আমার উত্তর ব্যবহার করার প্রস্তাব ।
মাইকেল পিফেল

53

ভাসমান পয়েন্টের মানগুলি কিছুটা হলেও বন্ধ হয়ে যেতে পারে, তাই তারা ঠিক সমান হিসাবে প্রতিবেদন করতে পারে না। উদাহরণস্বরূপ, "6.1" এ একটি ফ্লোট স্থাপন এবং তারপরে আবার মুদ্রণ করা, আপনি "6.099999904632568359375" এর মতো কোনও কিছুর একটি প্রতিবেদনিত মান পেতে পারেন। এটি ভাসমান কাজ করার জন্য মৌলিক; সুতরাং, আপনি তাদের সমতা ব্যবহার করে তুলনা করতে চান না, বরং একটি পরিসরের মধ্যে তুলনা করুন, এটি হ'ল যদি আপনি যে সংখ্যার সাথে তুলনা করতে চান তার সাথে ভাসমানের ভিন্নতা কোনও নির্দিষ্ট পরম মানের চেয়ে কম হয়।

নিবন্ধের এই নিবন্ধটি কেন এটি হয় তার একটি ভাল ওভারভিউ দেয়; দরকারী এবং আকর্ষণীয় পড়া।


@ কেভিন্ডিম: সুতরাং আপনি নিজের সমতা পরীক্ষা করতে পারবেন তবে যদি (সংখ্যা == 6.099999904632568359375) আপনি যে কোনও সময় নম্বর জানতে চান তবে এটি 6.1 এর সমান ... হ্যাঁ আপনি সঠিক ... কম্পিউটারে সমস্ত কিছু কঠোরভাবে নির্বিচারক, গণিতের সমস্যাগুলি করার সময় কেবলমাত্র ফ্লোটগুলির জন্য ব্যবহৃত অনুমানগুলি পাল্টা স্বজ্ঞাত।
নিউটোপিয়ান


1
@ স্টার্ট আমার ভুল হতে পারে, তবে আমি মনে করি না এফডিএল বাগটি অ-সংঘবদ্ধ ছিল। হার্ডওয়্যার দ্বারা প্রদত্ত উত্তরগুলি নির্দিষ্টকরণের সাথে সামঞ্জস্য হয় নি, তবে তারা নির্বিচারবাদী ছিল, একই হিসাব সর্বদা একই ভুল ফল তৈরি করেছিল
গ্র্যাভিটি

@ গ্র্যাভিটি আপনি যুক্তি দিতে পারেন যে কোনও আচরণ একটি নির্দিষ্ট সংক্ষিপ্ত সংকেত প্রদান করে নির্বিচারবাদী।
স্টুয়ার্ট পি। বেন্টলে

ভাসমান পয়েন্টের মানগুলি যথার্থ নয়। প্রতিটি ভাসমান পয়েন্টের মান হুবহু। ভাসমান পয়েন্ট গণনার ফলাফল যা অপ্রচলিত হতে পারে । তবে সাবধান! আপনি যখন কোনও প্রোগ্রামে ০.১ এর মতো কিছু দেখেন, এটি কোনও ভাসমান পয়েন্টের মান নয়। এটি একটি ভাসমান বিন্দু আক্ষরিক --- একটি স্ট্রিং যা সংকলক একটি গণনা করে ফ্লোটিং পয়েন্ট মান রূপান্তর করে ।
সলোমন আস্তে

22

বাকি সবাই কী বলছে এর পিছনে যুক্তি দেওয়া মাত্র।

একটি ভাসমান বাইনারি উপস্থাপনা বিরক্তিকর এক ধরণের।

বাইনারিতে, বেশিরভাগ প্রোগ্রামাররা 1 বি = 1 ডি, 10 বি = 2 ডি, 100 বি = 4 ডি, 1000 বি = 8 ডি এর মধ্যে পারস্পরিক সম্পর্ক জানে

ঠিক আছে এটি অন্যভাবে কাজ করে।

.1 বি = .5 ডি, .01 বি = .25 ডি, .001 বি = .125, ...

সমস্যাটি হ'ল .1, .2, .3, ইত্যাদির মতো সর্বাধিক দশমিক সংখ্যার প্রতিনিধিত্ব করার সঠিক কোনও উপায় নেই you সংখ্যাগুলি মুদ্রিত হলে সিস্টেমটি কিছুটা ঝাঁকুনি দেয় যাতে এটি .100000000000011 বা .999999999999 এর পরিবর্তে .1 প্রদর্শিত হয় (যা সম্ভবত .1 হিসাবে সঞ্চিত প্রতিনিধিত্বের খুব কাছেই রয়েছে)

মন্তব্য থেকে সম্পাদনা করুন: এ কারণে সমস্যাটি হ'ল আমাদের প্রত্যাশা। আমরা যখন it. or বা .67 or বা .6666666767 either এ দশমিক রূপান্তর করি তখন আমরা কোনও স্থানে ২/৩ টি সম্পূর্ণরূপে প্রত্যাশিত হওয়ার প্রত্যাশা করি .. তবে আমরা স্বয়ংক্রিয়ভাবে .1 কে 2/3 এর মতো করে গোল করার আশা করি না - এবং ঠিক কি ঘটছে।

যাইহোক, আপনি যদি কৌতূহলী হন তবে এটি অভ্যন্তরীণভাবে সংরক্ষণ করা সংখ্যাটি বাইনারি "বৈজ্ঞানিক স্বরলিপি" ব্যবহার করে খাঁটি বাইনারি উপস্থাপনা। সুতরাং আপনি যদি এটি দশমিক সংখ্যা 10.75 ডি সঞ্চয় করতে বলে থাকেন তবে এটি 10 ​​এর জন্য 1010 বি এবং দশমিকের জন্য .11b সংরক্ষণ করবে। সুতরাং এটি সংরক্ষণ করবে .101011 তারপরে এটি শেষে কয়েকটি বিট সংরক্ষণ করে: দশমিক পয়েন্টটি ডানদিকে ডানদিকে সরান Move

(যদিও প্রযুক্তিগতভাবে এটি এখন দশমিক বিন্দু নয়, এটি এখন একটি বাইনারি পয়েন্ট, তবে সেই পরিভাষাটি বেশিরভাগ লোকের পক্ষে এই বিষয়গুলিকে আরও বোধগম্য করে তুলতে পারত না যে কোনও ব্যবহারের এই উত্তরটি খুঁজে পেতে পারে))


1
@ ম্যাট কে - উম, স্থির বিন্দু নয়; যদি আপনি "দশমিক বিন্দু [এন] বিটকে ডানদিকে সরান" বলে কিছু বিট সংরক্ষণ করেন তবে এটি ভাসমান বিন্দু। ফিক্সড পয়েন্টটি ভাল, স্থির হিসাবে রেডিক্স পয়েন্টের অবস্থান নেয়। এছাড়াও, সাধারণভাবে, যেহেতু বিনামাল (?) পয়েন্টটি সর্বদা আপনাকে বাম দিকের অবস্থানে একটি '1' রেখে চলে যেতে পারে, আপনি এমন কিছু সিস্টেম খুঁজে পাবেন যা এইভাবে মুক্ত স্থানটিকে নিয়োজিত করে (1) অগ্রণী 'বাদ দেয়' (1 বিট!) এক্সপোনেন্টের পরিসর বাড়ানোর জন্য।
জাস্টজেফ

বাইনারি বনাম দশমিক প্রতিনিধির সাথে সমস্যার কোনও সম্পর্ক নেই। দশমিক ভাসমান-পয়েন্ট সহ, আপনার কাছে এখনও (1/3) * 3 == 0.9999999999999999999999999999 এর মতো জিনিস রয়েছে।
dan04

2
@ ডান04 হ্যাঁ, কারণ 1/3 এর দশমিক বা বাইনারি উপস্থাপনা নেই, এটির একটি ট্রাইনারি উপস্থাপনা আছে এবং সঠিকভাবে রূপান্তরিত হবে :)। আমি তালিকাভুক্ত সংখ্যা (.1, .25, ইত্যাদি) সমস্তের দশমিক নিখুঁত প্রতিনিধিত্ব রয়েছে তবে কোনও বাইনারি উপস্থাপনা নেই - এবং "সঠিক" উপস্থাপনা থাকা লোকদের ব্যবহার করা হয়। বিসিডি তাদের নিখুঁতভাবে পরিচালনা করবে। এটাই পার্থক্য।
বিল কে

1
এটিতে আরও বেশি উপায়ে নেওয়া উচিত, কারণ এটি সমস্যার পিছনে বাস্তব সমস্যাটি বর্ণনা করে।
লেভাইট

19

ভাসমান পয়েন্টের মানগুলি তুলনা করতে == ব্যবহার করে কী ভুল?

কারণ এটি সত্য নয় 0.1 + 0.2 == 0.3


7
কি Float.compare(0.1f+0.2f, 0.3f) == 0?
কুম্ভ শক্তি পাওয়ার

0.1f + 0.2f == 0.3f কিন্তু 0.1 ডি + 0.2 ডি! = 0.3 ডি। ডিফল্টরূপে, 0.1 + 0.2 একটি ডাবল। 0.3 একটি ডাবল হিসাবে।
বার্নাবাইরেলস

12

আমার মনে হয় ভাসমান (এবং ডাবলস) চারপাশে প্রচুর বিভ্রান্তি রয়েছে, এটি পরিষ্কার করা ভাল।

  1. স্ট্যান্ডার্ড-কমপ্লায়েন্ট জেভিএম [*] এর আইডি হিসাবে ফ্লোটগুলি ব্যবহার করার মধ্যে সহজাত ভুল নেই । আপনি যদি সহজেই x এ ফ্লোট আইডি সেট করেন তবে এটির সাথে কিছুই করবেন না (অর্থাত্ কোনও পাটিগণিত নয়) এবং পরে y == x এর জন্য পরীক্ষা করুন, আপনি ভাল হয়ে যাবেন। এগুলি হ্যাশম্যাপে কী হিসাবে ব্যবহার করার ক্ষেত্রে কোনও ভুল নেই। আপনি যা করতে পারবেন না তা হ'ল সমানত্ব গ্রহণ x == (x - y) + yইত্যাদি is এটি বলা হচ্ছে, মানুষ সাধারণত আইডি হিসাবে পূর্ণসংখ্যার প্রকার ব্যবহার করে এবং আপনি পর্যবেক্ষণ করতে পারেন যে এখানে বেশিরভাগ লোককে এই কোড দ্বারা বন্ধ করা হয়, তাই ব্যবহারিক কারণে, সম্মেলনগুলি মেনে চলা ভাল is । মনে রাখবেন যে doubleদীর্ঘ হিসাবে অনেকগুলি বিভিন্ন মান রয়েছে values, সুতরাং আপনি ব্যবহার করে কিছুই লাভ করবেন না double। এছাড়াও, "নেক্সট উপলভ্য আইডি" তৈরি করা ডাবলগুলির সাথে কৌতুকজনক হতে পারে এবং ভাসমান-পয়েন্ট গণিতের কিছু জ্ঞান প্রয়োজন। কষ্টের মূল্য নেই।

  2. অন্যদিকে, দুটি গাণিতিক সমতুল্য গণনার ফলাফলের সংখ্যাসমূহের উপর নির্ভর করা ঝুঁকিপূর্ণ। দশমিক থেকে বাইনারি উপস্থাপনায় রূপান্তর করার সময় এটি গোলাকার ত্রুটি এবং যথাযথতা হ্রাসের কারণ is এটি এসও-তে মৃত্যুর বিষয়ে আলোচনা হয়েছে।

[*] যখন আমি "স্ট্যান্ডার্ড-কমপ্লায়েন্ট জেভিএম" বলতাম তখন আমি কিছু মস্তিষ্ক-ক্ষতিগ্রস্থ জেভিএম বাস্তবায়ন বাদ দিতে চাইতাম। এই দেখুন ।


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

উপরের রেফারেন্স Float, না float
কোয়ান্ট_দেব

কি কথা বলছে Float? যদি কেউ অনন্য floatমানের একটি টেবিল তৈরি করার চেষ্টা করে এবং তাদের সাথে তুলনা করে ==, ভয়াবহ আইইইই -754 তুলনামূলক নিয়মের ফলস্বরূপ সারণিটি NaNমানগুলিতে প্লাবিত হবে ।
ক্যাট

floatটাইপ equalsপদ্ধতি নেই।
কোয়ান্ট_দেব

আহ - আমি একটি equalsউদাহরণ পদ্ধতি বোঝাতে চাইনি , বরং স্থির পদ্ধতিটি (আমি Floatশ্রেণীর মধ্যে মনে করি ) যা টাইপের দুটি মানের সাথে তুলনা করে float
সুপারক্যাট

9

এটি জাভা সম্পর্কিত নয় এমন একটি সমস্যা। দুটি ফ্লোট / ডাবল / যে কোনও দশমিক ধরণের সংখ্যার তুলনা করতে == ব্যবহার করা সম্ভবত তারা যেভাবে সংরক্ষণ করা হয়েছে তার কারণে সমস্যা তৈরি করতে পারে। একটি একক নির্ভুলতা ভাসমান (আইইইইই স্ট্যান্ডার্ড 754 অনুসারে) এর 32 টি বিট রয়েছে যা নীচে বিতরণ করা হয়েছে:

1 বিট - সাইন (0 = ধনাত্মক, 1 = negativeণাত্মক)
8 বিট - এক্সপোনেন্ট (একটি বিশেষ (পক্ষপাত -127) 2 x represent x এর উপস্থাপনা)
ণাত্মক 23 বিট - মান্টিসা। সঞ্চিত প্রকৃত সংখ্যা।

ম্যান্টিসার ফলেই সমস্যা হয়। এটি বৈজ্ঞানিক স্বরলিপি মত দারুণ, শুধুমাত্র বেস 2 (বাইনারি) এর সংখ্যাটি 1.110011 x 2 ^ 5 বা অনুরূপ কিছু দেখাচ্ছে। তবে বাইনারিটিতে প্রথম 1 সর্বদা 1 থাকে (0 টির প্রতিনিধিত্ব ব্যতীত)

অতএব, কিছুটা মেমোরি স্পেস সংরক্ষণের জন্য (শঙ্কিত উদ্দেশ্যে), আইইইই সিদ্ধান্ত নিয়েছিল যে 1 টি ধরে নেওয়া উচিত। উদাহরণস্বরূপ, 1011 এর একটি ম্যান্টিসার প্রকৃতপক্ষে 1.1011।

এটি তুলনার সাথে কিছু সমস্যা সৃষ্টি করতে পারে, প্রমিতভাবে 0 এর সাথে 0 যেহেতু সম্ভবত কোনও ফ্লোটে সঠিকভাবে উপস্থাপন করা যায় না। অন্যান্য উত্তর দ্বারা বর্ণিত ভাসমান পয়েন্ট গণিত ইস্যু ছাড়াও এটি == নিরুৎসাহিত হওয়ার মূল কারণ।

জাভাতে একটি অনন্য সমস্যা রয়েছে যে ভাষা বহুবিধ প্ল্যাটফর্ম জুড়ে সর্বজনীন, যার প্রত্যেকটিরই নিজস্ব অনন্য ফ্লোট বিন্যাস থাকতে পারে। এটি == এড়ানো আরও গুরুত্বপূর্ণ করে তোলে।

সমতার জন্য দুটি ভাসমান (ভাষা নির্দিষ্ট মন নয়) তুলনা করার সঠিক উপায়টি নীচে:

if(ABS(float1 - float2) < ACCEPTABLE_ERROR)
    //they are approximately equal

যেখানে ACCEPTABLE_ERROR # নির্ধারিত বা অন্য কিছু ধ্রুবক 0,000000001 সমান বা যা নির্ভুলতা প্রয়োজন, যেমন ভিক্টর ইতিমধ্যে উল্লিখিত হয়েছে।

কিছু ভাষার এই কার্যকারিতা বা এই ধ্রুবকটি অন্তর্নির্মিত থাকে তবে সাধারণত এটি থাকা ভাল অভ্যাস।


3
জাভা ভাসমান জন্য একটি সংজ্ঞায়িত আচরণ আছে। এটি প্ল্যাটফর্ম নির্ভর নয়।
যিশাই

9

আজকের হিসাবে এটি করার দ্রুত এবং সহজ উপায় হ'ল:

if (Float.compare(sectionID, currentSectionID) == 0) {...}

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

তবুও যদি উচ্চতর বা কাস্টমাইজড নির্ভুলতার প্রয়োজন হয় তবে

float epsilon = Float.MIN_NORMAL;  
if(Math.abs(sectionID - currentSectionID) < epsilon){...}

অন্য সমাধান বিকল্প।


1
আপনি যে দস্তাবেজগুলি সংযুক্ত করেছেন সেগুলিতে "f1 সংখ্যার সাথে f2 এর সমান হলে মান 0" বলা হয় যা (sectionId == currentSectionId)ভাসমান পয়েন্টগুলির জন্য সঠিক নয় এমনটি করার মতো করে তোলে । Epsilon পদ্ধতি ভাল পদ্ধতির, যা এই উত্তরে নন: stackoverflow.com/a/1088271/4212710
typoerrpr

8

রাউন্ডঅফ ত্রুটির কারণে ফোটিং পয়েন্টের মানগুলি নির্ভরযোগ্য নয়।

এগুলি সম্ভবত মূল মান হিসাবে ব্যবহার করা উচিত নয় যেমন সেকশনআইডি। পরিবর্তে পূর্ণসংখ্যার ব্যবহার করুন, অথবা longযদি intযথেষ্ট সম্ভাব্য মান ধারণ করে না।


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

2
বা একটি দীর্ঘ। ভবিষ্যতে কতগুলি অনন্য আইডি উত্পন্ন হয় তার উপর নির্ভর করে কোনও ইনট যথেষ্ট বড় নাও হতে পারে।
ওয়েইন হার্টম্যান

ভাসমানের তুলনায় দ্বিগুণ কতটা সঠিক?
অরবিন্দ মণি

1
@ অরবিন্দমণি doubleঅনেক বেশি সুনির্দিষ্ট, তবে সেগুলিও ভাসমান মূল্যের মান, তাই আমার উত্তরটি বোঝানো হয়েছিল floatএবং উভয়ই অন্তর্ভুক্ত করা double
এরিক উইলসন

7

পূর্ববর্তী উত্তরের পাশাপাশি, আপনার সচেতন হওয়া উচিত যে এর সাথে অদ্ভুত আচরণ যুক্ত রয়েছে -0.0fএবং +0.0f(সেগুলি ==তবে তা নয় equals) এবং Float.NaN(এটি তবে equalsতা নয় ==) (আশা করি আমি অধিকার পেয়েছি - আর্গ, এটি করবেন না!)।

সম্পাদনা করুন: চেক করা যাক!

import static java.lang.Float.NaN;
public class Fl {
    public static void main(String[] args) {
        System.err.println(          -0.0f   ==              0.0f);   // true
        System.err.println(new Float(-0.0f).equals(new Float(0.0f))); // false
        System.err.println(            NaN   ==               NaN);   // false
        System.err.println(new Float(  NaN).equals(new Float( NaN))); // true
    }
} 

আইইইই / 754 এ আপনাকে স্বাগতম।


যদি কিছু == হয়, তবে সেগুলি বিট থেকে অভিন্ন। তারা সমান হতে পারে না কিভাবে ()? আপনি এটা পিছনের দিকে আছে?
এম কে বি

@ ম্যাট নাএন বিশেষ। জাভাতে Double.isNaN (ডাবল এক্স) আসলে {রিটার্ন এক্স! = এক্স হিসাবে প্রয়োগ করা হয়; } ...
কোয়ান্ট_দেব

1
ভাসমানগুলির সাথে, এর ==অর্থ এই নয় যে সংখ্যাগুলি "বিটের সাথে একরকম" (একই সংখ্যাটি বিভিন্ন বিট নিদর্শনগুলির সাথে উপস্থাপন করা যেতে পারে, যদিও এর মধ্যে কেবল একটিই স্বাভাবিক ফর্ম)। পাশাপাশি, -0.0fএবং 0.0fবিভিন্ন বিট নিদর্শন দ্বারা প্রতিনিধিত্ব করা হয় (সাইন বিট পৃথক পৃথক), তবে এর সাথে সমান হিসাবে তুলনা করুন ==(তবে সাথে নয় equals)। আপনার ধারনা যা ==বিটওয়াইজ তুলনা, সাধারণভাবে বলা, ভুল।
পাভেল মিনায়েভ

6

আপনার এবং আপনার মুখোমুখি হতে পারে এমন আরও অনেক ভাসমান বিষয় সম্পর্কে এখানে একটি দীর্ঘ দীর্ঘ (তবে আশাবাদী কার্যকর) আলোচনা: ভাসমান-পয়েন্ট পাটিগণিত সম্পর্কে প্রতিটি কম্পিউটার বিজ্ঞানীর কী জানা উচিত


5

আপনি Float.floatToIntBits () ব্যবহার করতে পারেন।

Float.floatToIntBits(sectionID) == Float.floatToIntBits(currentSectionID)

1
তুমি কি সঠিক পথে আছো. ফ্লোটটোইন্টবিটস () হ'ল সঠিক উপায়, তবে এটি কেবলমাত্র ফ্লোটের বিল্ট ইক্যুয়াল () ফাংশনটিতে ব্যবহার করা সহজ হবে। এখানে দেখুন: স্ট্যাকওভারফ্লো . com / a / 3668105 / 2066079 । আপনি দেখতে পাচ্ছেন যে ডিফল্ট সমান () অভ্যন্তরীণভাবে ফ্লোটটোইন্টবিট ব্যবহার করে।
dberm22

1
হ্যাঁ তারা যদি ফ্লোট অবজেক্ট হয়। আপনি আদিমদের জন্য উপরের সমীকরণটি ব্যবহার করতে পারেন।
আমাদ্মি

4

প্রথমত, তারা ভাসা না ভাসা? যদি এর মধ্যে একটি ফ্লোট হয় তবে আপনার সমান () পদ্ধতিটি ব্যবহার করা উচিত। এছাড়াও, স্ট্যাটিক ফ্লোট ডটকম স্পেস পদ্ধতিটি ব্যবহার করা সম্ভবত সেরা।


4

নিম্নলিখিতটি স্বয়ংক্রিয়ভাবে সর্বোত্তম নির্ভুলতা ব্যবহার করে:

/**
 * Compare to floats for (almost) equality. Will check whether they are
 * at most 5 ULP apart.
 */
public static boolean isFloatingEqual(float v1, float v2) {
    if (v1 == v2)
        return true;
    float absoluteDifference = Math.abs(v1 - v2);
    float maxUlp = Math.max(Math.ulp(v1), Math.ulp(v2));
    return absoluteDifference < 5 * maxUlp;
}

অবশ্যই, আপনি কমপক্ষে 5 টি ইউএলপি বেছে নিতে পারেন ('শেষ স্থানে ইউনিট')।

আপনি যদি অ্যাপাচি কমন্স লাইব্রেরিতে থাকেন তবে Precisionক্লাসটি compareTo()এবং equals()অ্যাপসিলন এবং ইউএলপি উভয়ই রয়েছে।


ফ্লোটকে দ্বিগুণ করার সময়, এই পদ্ধতিটি ডাবলএকুয়াল হিসাবে কাজ করে না (0.1 + 0.2-0.3, 0.0) == মিথ্যা
হাইচাউ

এটিকে doubleআবরণ করার জন্য আপনাকে আরও 10_000_000_000_000_000_000L এর মতো প্রয়োজন বলে মনে হচ্ছে ।
মাইকেল পাইফেল


3

আপনার যদি * ফ্লোট ব্যবহার করতে হয়, তবে কড়াকড়ি কীওয়ার্ডটি কার্যকর হতে পারে।

http://en.wikipedia.org/wiki/strictfp


অথবা বিভিন্ন স্থাপত্যের জন্য আরও বেশি কার্যকর হতে পারে।
জোয় রোহান

2

দুটি ভিন্ন গণনা যা সমান আসল সংখ্যা উত্পাদন করে অগত্যা সমান ভাসমান পয়েন্ট সংখ্যা তৈরি করে না। গণনার ফলাফলের তুলনা করতে লোকেরা == ব্যবহার করে সাধারণত এটির দ্বারা অবাক হয়ে যায়, তাই সতর্কতাটি পতাকাটিকে সহায়তা করে যা অন্যথায় বাগের পুনরুত্পাদন করা একটি সূক্ষ্ম এবং কঠিন হতে পারে।


2

আপনি কি আউটসোর্স কোড ব্যবহার করছেন যা সেকশনআইডি এবং কারেন্টসেকশনআইডি নামের জিনিসগুলির জন্য ভাসমান ব্যবহার করবে? উৎসুক.

@ বিল কে: "ফ্লোটের দ্বৈত উপস্থাপনা এক প্রকার বিরক্তিকর।" তা কিভাবে? আপনি কিভাবে এটি আরও ভাল করতে হবে? কিছু নির্দিষ্ট নম্বর রয়েছে যা কোনও বেসে সঠিকভাবে উপস্থাপন করা যায় না, কারণ এগুলি কখনই শেষ হয় না। পাই একটি ভাল উদাহরণ। আপনি এটি প্রায় আনুমানিক করতে পারেন। আপনার আরও ভাল সমাধান থাকলে, ইন্টেলের সাথে যোগাযোগ করুন।


1

অন্যান্য উত্তরে উল্লিখিত হিসাবে, ডাবলসের ছোট বিচ্যুতি থাকতে পারে। এবং একটি "গ্রহণযোগ্য" বিচ্যুতি ব্যবহার করে তাদের তুলনা করতে আপনি নিজের পদ্ধতি লিখতে পারেন। যাহোক ...

দ্বিগুণ তুলনা করার জন্য একটি অ্যাপাচি শ্রেণি রয়েছে: org.apache.commons.math3.util.Precision

এটিতে কিছু আকর্ষণীয় ধ্রুবক রয়েছে: SAFE_MINএবংEPSILON এটি সাধারণ পাটিগণিতের অপারেশনের সর্বাধিক সম্ভাব্য বিচ্যুতি।

এটি তুলনা, সমান বা বৃত্তাকার দ্বিগুণ করার জন্য প্রয়োজনীয় পদ্ধতিগুলি সরবরাহ করে। (ইউএলপিএস বা পরম বিচ্যুতি ব্যবহার করে)


1

এক লাইনের উত্তরে আমি বলতে পারি, আপনার ব্যবহার করা উচিত:

Float.floatToIntBits(sectionID) == Float.floatToIntBits(currentSectionID)

সম্পর্কিত অপারেটরগুলি সঠিকভাবে ব্যবহার সম্পর্কে আপনাকে আরও শিখতে, আমি এখানে কয়েকটি কেস বিস্তারিতভাবে বর্ণনা করছি: সাধারণত জাভাতে স্ট্রিং পরীক্ষা করার জন্য তিনটি উপায় রয়েছে। আপনি ==, .Equals (), বা অবজেক্টস.কোয়্যালস () ব্যবহার করতে পারেন।

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

ব্যবহার করার জন্য আদর্শ অপারেটর to

ভাল এটি প্রচুর বিতর্কের বিষয় হয়েছে কারণ তিনটি অপারেটরের প্রত্যেকেই তাদের নিজস্ব শক্তি এবং দুর্বলতার স্বতন্ত্র সেট তৈরি করেছেন। উদাহরণস্বরূপ, == অবজেক্টের রেফারেন্সের তুলনা করার সময় প্রায়শই একটি পছন্দসই বিকল্প, তবে এমন ক্ষেত্রেও দেখা যায় যেখানে স্ট্রিংয়ের মানগুলিও তুলনা করা যায়।

যাইহোক, আপনি যা পান সেটি একটি ফলস মূল্য কারণ জাভা একটি ধারণা তৈরি করে যে আপনি মূল্যবোধের তুলনা করছেন তবে প্রকৃত অর্থে আপনি নন। নীচের দুটি ক্ষেত্রে বিবেচনা করুন:

মামলা 1:

String a="Test";
String b="Test";
if(a==b) ===> true

কেস 2:

String nullString1 = null;
String nullString2 = null;
//evaluates to true
nullString1 == nullString2;
//throws an exception
nullString1.equals(nullString2);

সুতরাং, এটির জন্য ডিজাইন করা নির্দিষ্ট বৈশিষ্ট্যটি পরীক্ষা করার সময় প্রতিটি অপারেটর ব্যবহার করা আরও ভাল। তবে প্রায় সব ক্ষেত্রেই অবজেক্টস.ইকোয়ালস () একটি আরও সার্বজনীন অপারেটর, সুতরাং ওয়েব বিকাশকারীরা এটির জন্য বেছে নিতে পারেন।

এখানে আপনি আরও বিশদ পেতে পারেন: http://fluentthemes.com/use-compare-strings-java/


-2

সঠিক উপায় হবে

java.lang.Float.compare(float1, float2)

7
Float.compare (float1, float2) একটি int প্রদান করে, সুতরাং এটি অবস্থায় অবস্থায় float1 == float2 এর পরিবর্তে ব্যবহার করা যাবে না। তদুপরি, এটি এই অন্তর্নিহিত সমস্যাটিকে প্রকৃতপক্ষে সমাধান করতে পারে না যা এই সতর্কতাটি উল্লেখ করছে - যে যদি ভাসমানগুলি সংখ্যার গণনার ফলাফল হয় তবে ফ্লোট 1! = ফ্লোট 2 কেবল গোলাকার ত্রুটির কারণে ঘটতে পারে।
কোয়ান্ট_দেব

1
ঠিক আছে, আপনি পেস্ট অনুলিপি করতে পারবেন না, আপনাকে প্রথমে ডকটি পরীক্ষা করতে হবে।
এরিক

2
ফ্লোট 1 == ফ্লোট 2 এর পরিবর্তে আপনি যা করতে পারেন তা হ'ল ফ্লোট ডট কম (ফ্লোট 1, ফ্লোট 2) == 0.
ডিটারব

29
এটি আপনাকে কোনও ক্রয় করে না - আপনি এখনও পানFloat.compare(1.1 + 2.2, 3.3) != 0
পাভেল মিনায়েভ

-2

রাউন্ডিং ত্রুটি হ্রাস করার একটি উপায় হ'ল ফ্লোটের চেয়ে দ্বিগুণ ব্যবহার। এটি সমস্যাটিকে দূরে সরিয়ে দেবে না, তবে এটি আপনার প্রোগ্রামে ত্রুটির পরিমাণ হ্রাস করবে এবং ভাসমানটি প্রায় কখনও সেরা পছন্দ নয়। এই প্রোগ্রামটিতে।

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