প্রথমত, ভাসমান পয়েন্টের মানগুলি তাদের আচরণে "এলোমেলো" নয়। সঠিক তুলনাটি বাস্তব-বিশ্বের ব্যবহারের প্রচুর পরিমাণে উপলব্ধি করতে পারে এবং তা করতে পারে। তবে আপনি যদি ভাসমান পয়েন্ট ব্যবহার করতে যাচ্ছেন তবে এটি কীভাবে কাজ করে সে সম্পর্কে আপনাকে সচেতন হওয়া দরকার। আসল সংখ্যার মতো ভাসমান পয়েন্ট কাজ করে ধরে নেওয়ার পক্ষে ত্রুটিযুক্ত হওয়া আপনাকে দ্রুত কোডটি ভেঙে দেওয়া কোডটি পেয়ে যাবে। ভাসমান পয়েন্টের ফলাফলগুলি ধরে নেওয়ার পক্ষে ত্রুটিযুক্ত এগুলির সাথে বড় এলোমেলো ঝাঁকুনি রয়েছে (বেশিরভাগ উত্তর এখানে প্রস্তাবিত হিসাবে) আপনাকে প্রথমে কাজ করবে বলে মনে হচ্ছে তবে বড় আকারের ত্রুটি এবং ভাঙা কোণার কেস থাকা শেষ করবে।
প্রথমত, আপনি যদি ভাসমান পয়েন্ট নিয়ে প্রোগ্রাম করতে চান তবে আপনার এটি পড়তে হবে:
প্রতিটি কম্পিউটার বিজ্ঞানী ভাসমান-পয়েন্ট পাটিগণিত সম্পর্কে যা জানা উচিত
হ্যাঁ, এটি সব পড়ুন। যদি এটি খুব বেশি বোঝা হয় তবে আপনার গণনার জন্য পূর্ণসংখ্যার / নির্দিষ্ট পয়েন্টটি ব্যবহার করা উচিত যতক্ষণ না আপনার এটি পড়ার সময় হয়। :-)
এখন, এই কথার সাথে, সঠিক ভাসমান পয়েন্ট তুলনা সহ সবচেয়ে বড় সমস্যাগুলি নেমে আসে:
সত্য যে মান প্রচুর আপনি উৎস লিখতে পারে, অথবা সঙ্গে পড়া scanf
বা strtod
, অস্তিত্ব নেই ফ্লোটিং পয়েন্ট মান হিসাবে এবং নিঃশব্দে নিকটতম পড়তা রূপান্তরিত হয়। দৈত্য demon73৩৩ এর উত্তর এটিই বলছিল।
আসল ফলাফল উপস্থাপনের যথেষ্ট যথাযথতা না থাকার কারণে অনেকগুলি ফলাফল গোল হয়ে যায়। একটি সহজ উদাহরণ যেখানে আপনি এটি দেখতে পাচ্ছেন এটি যোগ করা x = 0x1fffffe
এবং y = 1
ভাসমান হিসাবে রয়েছে। এখানে x
মান্টিসায় 24 টি বিট আছে (ঠিক আছে) এবং y
মাত্র 1 বিট রয়েছে তবে আপনি যখন এগুলি যুক্ত করেন তখন তাদের বিটগুলি ওভারল্যাপিং জায়গায় হয় না এবং ফলস্বরূপ 25 বিট নির্ভুলতার প্রয়োজন হয়। পরিবর্তে, এটি গোল হয়ে যায় ( 0x2000000
ডিফল্ট রাউন্ডিং মোডে)।
সঠিক মানের জন্য অসীম অনেক জায়গার প্রয়োজনের ফলে অনেকগুলি ফলাফল বৃত্তাকার হয়ে যায়। এর মধ্যে উভয় যুক্তিযুক্ত ফলাফল অন্তর্ভুক্ত রয়েছে 1/3 (যেমন আপনি দশমিকের সাথে পরিচিত যেখানে এটি অসীম অনেক জায়গাতে নিয়ে যায়) তবে 1/10 (যা বাইনারিতেও অসীম অনেকগুলি স্থান নেয়, যেহেতু 5 টি 2 এর শক্তি নয়), পাশাপাশি অযৌক্তিক ফলাফলগুলির মতো কোনও বর্গমূলের মতো যা কোনও নিখুঁত বর্গ নয়।
ডাবল রাউন্ডিং। কিছু সিস্টেমে (বিশেষত x86), ভাসমান পয়েন্ট এক্সপ্রেশনগুলি তাদের নামমাত্র ধরণের চেয়ে উচ্চতর নির্ভুলতায় মূল্যায়ন করা হয়। এর অর্থ এই যে যখন উপরের কোনও ধরণের রাউন্ডিং ঘটে তখন আপনি দুটি বৃত্তাকার পদক্ষেপ পাবেন, প্রথমে ফলাফলটি উচ্চ-নির্ভুলতার ধরণের, পরে চূড়ান্ত প্রকারের গোলাকার। উদাহরণস্বরূপ, দশমিকের মধ্যে কী ঘটে যায় তা বিবেচনা করুন যদি আপনি কোনও সংখ্যার (১) এর সাথে ১.৪৪ গোল করেন তবে আপনি যদি প্রথমে এটি একটি দশমিক স্থানে (1.5) গোল করেন তবে ফলাফলটি পূর্ণসংখ্যায় পরিণত হয় (2)। ভাসমান পয়েন্টটি মোকাবেলা করার জন্য এটি প্রকৃতপক্ষে একটি নস্টিস্ট অঞ্চল, যেহেতু সংকলকটির আচরণ (বিশেষত বগি, জিসিসির মতো না-অনুমানকারী সংকলকগুলির জন্য) অনাকাঙ্ক্ষিত।
অতীন্দ্রিয় ফাংশন ( trig
, exp
, log
, ইত্যাদি) সঠিকভাবে বৃত্তাকার ফলাফল নির্দিষ্ট করা হয় না; ফলাফলটি সুনির্দিষ্টতার শেষ স্থানে (সাধারণত 1ulp হিসাবে পরিচিত ) এক ইউনিটের মধ্যে সঠিক হতে নির্দিষ্ট করা হয়েছে ।
আপনি যখন ভাসমান পয়েন্ট কোডটি লিখছেন, তখন আপনাকে সেই সংখ্যাগুলি দিয়ে কী করছেন যেগুলি ফলাফলটি অকার্যকর হতে পারে এবং সেই অনুযায়ী তুলনা করা উচিত তা আপনার মনে রাখা প্রয়োজন। প্রায়শই একটি "অ্যাপসিলন" এর সাথে তুলনা করা বুদ্ধিমান হয়ে উঠবে, তবে সেই অ্যাপসিলনটি আপনি যে সংখ্যার সাথে তুলনা করছেন তার परिमाणের ভিত্তিতে হওয়া উচিত , একেবারে ধ্রুবক নয় not (যে ক্ষেত্রে নিরঙ্কুশ ধ্রুবক এপসিলন কাজ করবে, এটি দৃ indic়ভাবে নির্দেশক যে স্থির বিন্দু, ভাসমান বিন্দু নয়, এটি কাজের সঠিক সরঞ্জাম!)
সম্পাদনা: বিশেষত, একটি परिमाण-সম্পর্কিত আপেলসোন চেকটির মতো দেখতে হবে:
if (fabs(x-y) < K * FLT_EPSILON * fabs(x+y))
কোথা FLT_EPSILON
থেকে ধ্রুবক রয়েছে float.h
( এর DBL_EPSILON
জন্য double
বা এর LDBL_EPSILON
জন্য এটি প্রতিস্থাপন করুন long double
) এবং আপনি K
এমন ধ্রুবক হিসাবে বেছে বেছে বেছে বেছেছেন যে আপনার গুনে জমা হওয়া ত্রুটিটি অবশ্যই স্থায়ীভাবে K
ইউনিট দ্বারা আবদ্ধ হয় (এবং যদি আপনি নিশ্চিত না হন যে ত্রুটিটি পেয়েছেন তবে আবদ্ধ গণনা ডান, K
আপনার গণনা যা বলেছিল তার থেকে কয়েকগুণ বড় করুন)।
পরিশেষে, নোট করুন যে আপনি এটি ব্যবহার করেন তবে শূন্যের কাছাকাছি কিছু বিশেষ যত্নের প্রয়োজন হতে পারে, যেহেতু FLT_EPSILON
ডেনারমালগুলি বোঝায় না। একটি দ্রুত সমাধান এটি করা হবে:
if (fabs(x-y) < K * FLT_EPSILON * fabs(x+y) || fabs(x-y) < FLT_MIN)
এবং একইভাবে বিকল্প DBL_MIN
যদি ডাবল ব্যবহার করে।
fabs(x+y)
সমস্যাযুক্ত যদিx
এবংy
(থাকতে পারে) আলাদা চিহ্ন থাকতে পারে। তবুও, কার্গো-কাল্ট তুলনার জোয়ারের বিরুদ্ধে একটি ভাল উত্তর।