CodeGym /Java Blog /এলোমেলো /জাভাতে BigDecimal
John Squirrels
লেভেল 41
San Francisco

জাভাতে BigDecimal

এলোমেলো দলে প্রকাশিত
ওহে! আজকের পাঠে, আমরা বড় সংখ্যা সম্পর্কে কথা বলব। না, আমি সত্যিই বড় মানে. আমরা পূর্বে বারবার আদিম ডেটা টাইপের জন্য মান রেঞ্জের টেবিলের সম্মুখীন হয়েছি। এটি এই মত দেখায়:
আদিম প্রকার স্মৃতিতে আকার মান পরিসীমা
বাইট 8 বিট -128 থেকে 127
সংক্ষিপ্ত 16 বিট -32768 থেকে 32767
চর 16 বিট 0 থেকে 65536
int 32 বিট -2147483648 থেকে 2147483647
দীর্ঘ 64 বিট -9223372036854775808 থেকে 9223372036854775807
ভাসা 32 বিট (2 থেকে -149 এর ঘাত) থেকে ((2 -23-এর ঘাত থেকে) * 2 থেকে 127-এর শক্তি)
দ্বিগুণ 64 বিট (-2 থেকে 63 এর শক্তি) থেকে (2 থেকে 63 এর শক্তি) - 1)
বুলিয়ান 8 (যখন অ্যারেতে ব্যবহার করা হয়), 32 (যখন অ্যারেতে ব্যবহার করা হয় না) সত্য অথবা মিথ্যা
রুমিয়েস্ট ইন্টিজার ডাটা টাইপ হল লম্বা । ফ্লোটিং-পয়েন্ট সংখ্যার ক্ষেত্রে এটি দ্বিগুণ । কিন্তু যদি আমাদের প্রয়োজনের সংখ্যাটি এত বড় হয় যে এটি একটি দীর্ঘ সময়ের মধ্যেও খাপ খায় না ? লং ডেটা টাইপের সম্ভাব্য মানগুলির একটি বেশ বড় পরিসর রয়েছে, তবে এটি এখনও 64 বিটের মধ্যে সীমাবদ্ধ। আমাদের খুব বড় সংখ্যার জন্য 100 বিট প্রয়োজন হলে আমাদের কী নিয়ে আসতে হবে? সৌভাগ্যবশত, আমাদের কিছু উদ্ভাবনের দরকার নেই। এই ধরনের ক্ষেত্রে, জাভা দুটি বিশেষ ক্লাস আছে: BigInteger (পূর্ণসংখ্যার জন্য) এবং BigDecimal(ফ্লোটিং-পয়েন্ট সংখ্যার জন্য)। কি তাদের বিশেষ করে তোলে? প্রথমত, তত্ত্বগতভাবে, তাদের সর্বোচ্চ আকার নেই। আমরা "তত্ত্বে" বলি, কারণ অসীম মেমরি সহ কোন কম্পিউটার নেই। এবং যদি আপনার প্রোগ্রামটি উপলব্ধ মেমরির পরিমাণের চেয়ে বড় একটি সংখ্যা তৈরি করে, তবে অবশ্যই, প্রোগ্রামটি কাজ করবে না। কিন্তু এই ধরনের ঘটনা অসম্ভাব্য। ফলস্বরূপ, আমরা বলতে পারি যে BigInteger এবং BigDecimal কার্যত সীমাহীন আকারের সংখ্যা উপস্থাপন করতে পারে। এই ক্লাস কি জন্য ব্যবহার করা হয়? প্রথমত, অত্যন্ত কঠোর নির্ভুলতার প্রয়োজনীয়তার সাথে গণনার জন্য। উদাহরণস্বরূপ, মানুষের জীবন কিছু প্রোগ্রামে (যেমন সফ্টওয়্যার যা বিমান, রকেট বা চিকিৎসা সরঞ্জাম নিয়ন্ত্রণ করে) গণনার নির্ভুলতার উপর নির্ভর করতে পারে। তাই যদি 150 তম দশমিক স্থান গুরুত্বপূর্ণ হয়, তাহলে BigDecimalসেরা পছন্দ। এছাড়াও, এই শ্রেণীর বস্তুগুলি প্রায়শই অর্থের জগতে ব্যবহৃত হয়, যেখানে এমনকি ক্ষুদ্রতম মানগুলির সঠিক গণনাও অত্যন্ত গুরুত্বপূর্ণ। আপনি কিভাবে BigInteger এবং BigDecimal অবজেক্টের সাথে কাজ করবেন এবং আপনার কি সেগুলি সম্পর্কে জানা দরকার? এই শ্রেণীর অবজেক্ট এই মত তৈরি করা হয়:

public class Main {

   public static void main(String[] args) {

       BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
       System.out.println(integer);

       BigDecimal decimal = new BigDecimal("123.444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444");
       System.out.println(decimal);
   }
}
কনস্ট্রাক্টরের কাছে একটি স্ট্রিং পাস করা শুধুমাত্র একটি সম্ভাব্য বিকল্প। এখানে আমরা স্ট্রিংগুলি ব্যবহার করি, কারণ আমাদের সংখ্যাগুলি দীর্ঘ এবং দ্বিগুণের জন্য সর্বাধিক মানগুলি ছাড়িয়ে গেছে এবং আমরা যে সংকলকটি তৈরি করতে চাই তা ব্যাখ্যা করার জন্য আমাদের কিছু উপায় প্রয়োজন :) কেবলমাত্র 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 কনস্ট্রাক্টরের কাছে কাজ করবে না: জাভা পাস করা নম্বরটিকে আদিম ডেটা টাইপগুলির মধ্যে একটিতে ক্র্যাম করার চেষ্টা করবে, কিন্তু এটি তাদের কোনোটিতেই ফিট হবে না। তাই পছন্দসই নম্বর পাস করার জন্য একটি স্ট্রিং ব্যবহার করা একটি ভাল বিকল্প। উভয় ক্লাসই পাস করা স্ট্রিং থেকে স্বয়ংক্রিয়ভাবে সংখ্যাসূচক মান বের করতে পারে। বড়-সংখ্যার ক্লাসগুলির সাথে কাজ করার সময় আরেকটি গুরুত্বপূর্ণ বিষয় মনে রাখবেন যে তাদের বস্তুগুলি অপরিবর্তনীয় ( অপরিবর্তনীয় )। আপনি ইতিমধ্যেই অপরিবর্তনীয়তার সাথে পরিচিত হয়েছেন স্ট্রিং ক্লাসের সাথে আপনার অভিজ্ঞতার জন্য এবং আদিম প্রকারের (পূর্ণসংখ্যা, লং, ইত্যাদি) র্যাপার ক্লাসের সাথে।

import java.math.BigInteger;

public class Main {

   public static void main(String[] args) {

       BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
       System.out.println(integer);

       integer.add(BigInteger.valueOf(33333333));
       System.out.println(integer);

   }
}
কনসোল আউটপুট:

11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 
আপনি যেমন আশা করবেন, আমাদের নম্বর পরিবর্তন হয়নি। সংযোজন অপারেশন সঞ্চালনের জন্য, আপনাকে অপারেশনের ফলাফল পেতে একটি নতুন বস্তু তৈরি করতে হবে।

import java.math.BigInteger;

public class Main {

   public static void main(String[] args) {

       BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
       System.out.println(integer);

       BigInteger result = integer.add(BigInteger.valueOf(33333333));
       System.out.println(result);

   }
}
কনসোল আউটপুট:

11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111144444444
দেখুন, এখন সবকিছু যেমন উচিত তেমন কাজ করে :) যাইহোক, আপনি কি লক্ষ্য করেছেন যে সংযোজন অপারেশনটি কতটা অস্বাভাবিক দেখাচ্ছে?

BigInteger result = integer.add(BigInteger.valueOf(33333333));
এটি আরেকটি গুরুত্বপূর্ণ পয়েন্ট। বড়-সংখ্যার ক্লাসগুলি + - * / অপারেটরগুলি ব্যবহার করে না। পরিবর্তে, তারা পদ্ধতির একটি সেট প্রদান করে। আসুন প্রধানগুলির সাথে পরিচিত হই (সর্বদা হিসাবে, আপনি ওরাকল ডকুমেন্টেশনে পদ্ধতিগুলির একটি সম্পূর্ণ তালিকা পেতে পারেন: এখানে এবং এখানে )।
  1. গাণিতিক ক্রিয়াকলাপের জন্য পদ্ধতি: add() , বিয়োগ () , multiply() , divide() । এই পদ্ধতিগুলি যথাক্রমে যোগ, বিয়োগ, গুণ এবং ভাগ করতে ব্যবহৃত হয়।

  2. doubleValue() , intValue() , floatValue() , longValue() ইত্যাদি একটি বড় সংখ্যাকে জাভার আদিম প্রকারের একটিতে রূপান্তর করতে ব্যবহৃত হয়। এই পদ্ধতিগুলি ব্যবহার করার সময় সতর্কতা অবলম্বন করুন। বিট আকারের পার্থক্য সম্পর্কে ভুলবেন না!

    
    import java.math.BigInteger;
    
    public class Main {
    
       public static void main(String[] args) {
    
           BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
    
           long result = integer.longValue();
           System.out.println(result);
    
       }
    }
    

    কনসোল আউটপুট:

    
    8198552921648689607
    
  3. min() এবং max() আপনাকে দুটি বড় সংখ্যার সর্বনিম্ন এবং সর্বোচ্চ মান খুঁজে পেতে দেয়।
    মনে রাখবেন যে এই পদ্ধতিগুলি স্ট্যাটিক নয়!

    
    import java.math.BigInteger;
    
    public class Main {
    
       public static void main(String[] args) {
    
           BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
           BigInteger integer2 = new BigInteger("222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222");
    
           System.out.println(integer.max(integer2));
    
       }
    }
    

    কনসোল আউটপুট:

    
    222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
    

BigDecimal রাউন্ডিং আচরণ

এই বিষয়ের নিজস্ব আলাদা বিভাগ রয়েছে, যেহেতু বড় সংখ্যাগুলিকে রাউন্ডিং করা এবং রাউন্ডিং আচরণ কনফিগার করা এত সহজ নয়৷ আপনি একটি BigDecimal- এর জন্য দশমিক স্থানের সংখ্যা নির্ধারণ করতে setScale() পদ্ধতি ব্যবহার করতে পারেন । উদাহরণস্বরূপ, ধরুন আমরা চাই 111.5555555555 সংখ্যাটিতে দশমিক বিন্দুর পরে তিনটি সংখ্যা থাকুক। যাইহোক, setScale() পদ্ধতিতে আর্গুমেন্ট হিসাবে 3 নম্বর পাস করে আমরা যা চাই তা অর্জন করতে পারি না । উপরে উল্লিখিত হিসাবে, BigDecimalকম্পিউটেশনাল নির্ভুলতার উপর কঠোর প্রয়োজনীয়তা সহ সংখ্যার প্রতিনিধিত্ব করার জন্য। বর্তমান আকারে, আমাদের সংখ্যার দশমিক বিন্দুর পরে 10টি সংখ্যা রয়েছে। আমরা তাদের মধ্যে 7টি ড্রপ করতে চাই এবং শুধুমাত্র 3টি রাখতে চাই। সেই অনুযায়ী, 3 নম্বর ছাড়াও, আমাদের অবশ্যই রাউন্ডিং মোডটি পাস করতে হবে। BigDecimal-এ মোট 8টি রাউন্ডিং মোড রয়েছে৷ এটাই অনেক! কিন্তু আপনি যদি সত্যিই আপনার গণনার নির্ভুলতাকে সূক্ষ্মভাবে সুরক্ষিত করতে চান, তাহলে আপনার যা যা প্রয়োজন তা আপনার কাছে থাকবে। সুতরাং, এখানে BigDecimal দ্বারা অফার করা 8টি রাউন্ডিং মোড রয়েছে :
  1. ROUND_CEILING — রাউন্ড আপ

    
    111.5555555555 -> setScale(3, ROUND_CEILING) -> 111.556
    
  2. ROUND_DOWN — শূন্যের দিকে রাউন্ড

    
    111.5555555555 -> setScale(3, ROUND_DOWN) -> 111.555
    
  3. ROUND_FLOOR — বৃত্তাকার নিচে

    
     111.5555555555 -> setScale(3, ROUND_FLOOR) -> 111.555
    
    

  4. ROUND_HALF_UP — দশমিক বিন্দুর পরে সংখ্যা হলে রাউন্ড আপ হয় >= 0.5

    
    0.55 -> setScale(1, ROUND_HALF_UP) -> 0.6
    0.54 -> setScale(1, ROUND_HALF_UP) -> 0.5
    
  5. ROUND_HALF_DOWN — দশমিক বিন্দু > 0.5 এর পরে সংখ্যা হলে রাউন্ড আপ হয়

    
    0.55 -> setScale(1, ROUND_HALF_DOWN) -> 0.5
    0.56 -> setScale(1, ROUND_HALF_DOWN) -> 0.6
    
  6. ROUND_HALF_EVEN — রাউন্ডিং দশমিক বিন্দুর বাম দিকের সংখ্যার উপর নির্ভর করে। বাম দিকের সংখ্যা জোড় হলে, রাউন্ডিং কম হবে। যদি দশমিক বিন্দুর বাম দিকের সংখ্যাটি বিজোড় হয়, তাহলে রাউন্ডিং আপ হবে।

    
    2.5 -> setScale(0, ROUND_HALF_EVEN) -> 2
    

    দশমিক স্থানের বাম দিকের সংখ্যাটি 2 (জোড়)। সংখ্যা বৃত্তাকার ডাউন হয়. আমরা 0 দশমিক স্থান চাই, তাই ফলাফল 2।

    
    3.5 -> setScale(0, ROUND_HALF_EVEN) -> 4
    

    দশমিক বিন্দুর বাম দিকের সংখ্যাটি 3 (বিজোড়)। সংখ্যাটি রাউন্ড আপ করা হয়েছে। আমরা 0 দশমিক স্থান চাই, তাই ফলাফল 4।

  7. ROUND_UNNECCESSARY — এই মোডটি ব্যবহার করা হয় যখন আপনাকে একটি পদ্ধতিতে একটি রাউন্ডিং মোড পাস করতে হবে, কিন্তু সংখ্যাটি বৃত্তাকার করার প্রয়োজন নেই৷ আপনি যদি ROUND_UNNECCESSARY মোড সেটের মাধ্যমে একটি সংখ্যাকে বৃত্তাকার করার চেষ্টা করেন, একটি পাটিগণিত ব্যতিক্রম নিক্ষেপ করা হয়।

    
    3.51 -> setScale(1, ROUND_UNNECCESSARY) -> ArithmeticException
    
  8. ROUND_UP — শূন্য থেকে রাউন্ড দূরে।

    
    111.5551 -> setScale(3, ROUND_UP) -> 111.556
    

বড় সংখ্যা তুলনা

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

import java.math.BigDecimal;

public class Main {

   public static void main(String[] args) {

       Double a = 1.5;
       Double b = 1.50;

       System.out.println(a.equals(b));

       BigDecimal x = new BigDecimal("1.5");
       BigDecimal y = new BigDecimal("1.50");

       System.out.println(x.equals(y));
      
   }
}
কনসোল আউটপুট:

true 
false
আপনি দেখতে পাচ্ছেন, BigDecimal- এর জন্য , 1.5 এবং 1.50 সংখ্যাগুলি অসম হয়ে উঠেছে! বিগডেসিমাল ক্লাসে equals() পদ্ধতির বাস্তবায়নের সুনির্দিষ্ট কারণে এটি হয়েছিল । দুটি BigDecimal বস্তুর আরও সঠিক তুলনার জন্য , compareTo() পদ্ধতিটি ব্যবহার করা ভাল :

import java.math.BigDecimal;

public class Main {

   public static void main(String[] args) {

       BigDecimal x = new BigDecimal("1.5");
       BigDecimal y = new BigDecimal("1.50");

       System.out.println(x.compareTo(y));

   }
}
কনসোল আউটপুট:

0
compareTo () পদ্ধতিটি 0 প্রদান করেছে, যার মানে হল 1.5 এবং 1.50 সমান। এবং এই ফলাফল আমরা প্রত্যাশিত! :) যে আজ আমাদের পাঠ সমাপ্তি. এখন কাজ ফিরে পেতে সময়! :)
মন্তব্য
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION