ফ্লোটিং পয়েন্ট রিপ্রেজেন্টেশন

Photo by Volkan Olmez on Unsplash

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

এটা কি হল? কেনই বা হল?

আপনার এত পাওয়ারফুল কম্পিউটার দুটি সংখ্যা ঠিকমত যোগই করতে পারে নাহ। কিন্তু কেন? আর হ্যাঁ, এটা কিন্তু জাভাস্ক্রিপ্টের দোষ না। সব প্রোগ্রামিং ল্যাঙ্গুয়েজেই এই সমস্যা থাকার কথা।

এটা আসলে হয় ফ্লোটিং পয়েন্ট রিপ্রেজেন্টেশনের জন্য। মানে কম্পিউটার যেভাবে ফ্লোটিং পয়েন্ট সংখ্যা মেমরিতে রাখে সেভাবে সব সংখ্যা সঠিকভাবে রাখা যায় না। তাই এই সমস্যা হয়। কম্পিউটার কিভাবে ফ্লোটিং পয়েন্ট নাম্বার মেমরিতে রাখে আর ঠিক কেনই বা সমস্যাটি হয়? খুব সহজ ভাষায় লেখার চেষ্টা করব।

কম্পিউটার মেমরিতে শুধু পূর্ণ সংখ্যা রাখতে পারে। আসুন আমরা নিজেরা ভেবে পূর্ণ সংখ্যা দিয়ে দশমিক ভগ্নাংশযুক্ত সংখ্যা রাখার একটা সিস্টেম বের করে ফেলি। আমার মাথায় একটা সহজ বুদ্ধি আসছে। আমরা একটি সংখ্যা 0.125 এর দশমিক বিন্দু ছাড়া শুধু 125 একটি পূর্ণ সংখ্যা হিসেবে রাখতে পারি। তারপর আরেকটি পূর্ণ সংখ্যা 3 রাখতে পারি। মানে পেছন থেকে তিন ঘর সামনে দশমিক বিন্দু দিতে হবে। তাহলে কাজ হয় না? চমৎকার।
এখন সমস্যা হল কম্পিউটার কিন্তু সবকিছু বাইনারিতে রাখবে। 125 কে বাইনারিতে নিলে হয় 1111101, এই বাইনারির তিন ঘর সামনে দশমিক বিন্দু দিলে কিন্তু আমরা আর .125 পাব না। তারপরেও এভাবে রাখা যাবে। ডেসিমেলে কনভার্ট করে তিন ঘর আগে দশমিক দিয়ে বিন্দু দিয়ে ঠিকই সংখ্যাটি দেখানো যাবে। কিন্তু যোগ, বিয়োগ, গুণ, ভাগ ইত্যাদি করা খুবই অসুবিধাজনক ও ইনইফিসিয়েন্ট হয়ে যাবে। যদি সংখ্যাটির উপর কোন অপারেশনই করা না যায়, তাহলে রেখে লাভ কি?

যদি সংখ্যাটির বাইনারি ফর্মে কত ঘর সামনে দশমিক বিন্দু দিতে হবে সেটা সেভ করে রাখতে পারি তাহলে সবকিছু বেশ ইফিসিয়েন্টলি করা যাবে। তাহলে কিভাবে হিসাব করব বাইনারি ফর্মে কত ঘর সামনে যেতে হবে? আগে দেখি দশমিকের ক্ষেত্রে ব্যাপারটা গাণিতিকভাবে কেমন হয়।

মানে তিন ঘর। বইনারির ক্ষেত্রে ভিত্তি হবে 10 এর বদলে 2।

তাহলে দশমিক বিন্দু ছাড়া সংখ্যাটি হবে 1 (যাকে বাইনারিতে নিলেও 1 ই হয়) আর তার তিন ঘর সামনে দশমিক বিন্দু দিতে হবে। তাহলে বাইনারিতে সংখ্যাটি হবে 0.001। এবার আমরা .1 কে এই পদ্ধতিতে রাখতে চেষ্টা করি।

এখন এটাকে কি করব? কিছুই করা যাবে না। এই পদ্ধতিতে আমরা কখনোই .1 রাখতে পারব না। তাহলে কি করা যায়? .1 না রেখে এর কাছাকাছি কোন সংখ্যা রাখতে পারি। যেমন 0.10009765625

নোট: বাস্তবে এই ত্রুটি আরো কম হয় অবশ্যই অর্থাৎ আরো কাছাকাছি সংখ্যা রাখা হয়।

তাহলে সংখ্যাটি বাইনারিতে এভাবে রাখতে হবে, 11001101 (205) আর তার 1011 (11) ঘর সামনে দশমিক বিন্দু। তাহলে আমরা দেখতে পাচ্ছি কম্পিউটারে সকল ভগ্নাংশযুক্ত সংখ্যা ঠিকভাবে রাখা যায় না। কিছু কিছু সংখ্যা রাখার ক্ষেত্রে কিছুটা ত্রুটি থেকে যায়। আবার সেই ত্রুটিযুক্ত সংখ্যা অন্য সংখ্যার সাথে যোগ বিয়োগ গুণ বা ভাগ করলে ফলাফলও ত্রুটিযুক্ত হয়। এজন্য প্রোগ্রামিং এ ফ্লোটিং পয়েন্ট সংখ্যা নিয়ে কাজ করার সময় আমাদের সাবধান থাকতে হয়। বিশেষ করে দুটি সংখ্যা তুলনা করার সময়। যেমন x = .1, y = .2 হলে আমরা আশা করব x + y == .3 হবে। কিন্তু আমরা কি দেখি?

পাইথন এক্সাম্পল

তাহলে দেখা যাচ্ছে দুটি ফ্লোটিং পয়েন্ট নাম্বার সরাসরি তুলনা করলে সমস্যা হতে পারে। আমরা দেখতে পারি সংখ্যা দুটি প্রায় সমান কিনা। অর্থাৎ তাদের পার্থক্য খুবই ছোট কিনা। তাদের পার্থক্য নিয়ে দেখতে পারি সেটি একটি অতি ক্ষুদ্র সংখ্যা eps থেকে ছোট কি না।

একইভাবে ≤, ≥, <, > এর জন্যও eps ব্যবহার করে তুলনা করতে হবে।


শুধু কম্পিউটার না, আমাদের দশমিক ব্যবস্থাও কিন্তু পারফেক্ট না। মনে করুন এক কেজি রসমলাই তিনজনের মধ্যে সমানভাবে ভাগ করে দিলেন। তাহলে সবাই কত কেজি করে পাবে? .33 কেজি করে। এখন যদি সবার থেকে আবার ফেরত নেন তাহলে কত কেজি ফেরত পাবেন? .33 + .33 + .33 = .99 কেজি। যদিও কেউ খায়নি, .01 কেজি উধাও। এটা হয় কারণ 1/3 সংখ্যাটিকে সঠিকভাবে দশমিকে প্রকাশ করা যায় না। এই ভগ্নাংশটিকে আপনি 2/6, 10/30 যেভাবেই লেখেন, হরকে 10 এর এক্সপোনেন্ট আকারে প্রকাশ করতে পারবেন না। তাই একে সঠিকভাবে দশমিকে প্রকাশ করা যায় না। আমরা বরং কাছাকাছি একটা সংখ্যা দিয়ে একে প্রকাশ করি।


লেখাটি অনেকের কাছেই লেইম মনে হতে পারে। অনেক কিছুই ওভার সিম্প্লিফাই করে ফেলেছি হয়ত। তারপরেও এটি পড়ে অনেকেই ব্যাপারটা সম্পর্কে একটা ধারণা পাবে বলে আশা করি। পড়ার জন্য ধন্যবাদ। অবশ্যই জানাবেন কেমন লাগল।