পাঠ ২৬ · ৪৪-এর মধ্যে · মডিউল ৫
Home / Courses / Discrete Mathematics / মডুলার এরিথমেটিক

মডুলার এরিথমেটিক

Modular arithmetic
৮ মিনিট পড়া মাঝারি · Intermediate Python কোডসহ সম্পূর্ণ বাংলায়

এই পাঠে যা শিখবেন

  • Congruence মডুলো $n$-এর আনুষ্ঠানিক সংজ্ঞা ও "ক্লক এরিথমেটিক" স্বজ্ঞা
  • মডুলার যোগ ও গুণের ধর্ম
  • দ্রুত মডুলার এক্সপোনেনশিয়েশন (repeated squaring) কীভাবে কাজ করে
  • মডুলার ইনভার্স কী, এবং কখন এর অস্তিত্ব থাকে
  • Python-এর বিল্ট-ইন pow(base, exp, mod) ও pow(a, -1, n) ব্যবহার

১ · Congruence — "ক্লক এরিথমেটিক"

CongruenceCongruence Modulo nদুটি পূর্ণসংখ্যা $a,b$ একে অপরের congruent মডুলো $n$, লেখা হয় $a \equiv b \pmod n$, যদি $n$ তাদের পার্থক্য $(a-b)$-কে ভাগ করে — সমতুল্যভাবে, $n$ দিয়ে ভাগ করলে দুজনের ভাগশেষ একই হয়। আমাদের প্রতিদিনের ঘড়ির মধ্যেই লুকিয়ে আছে। ঘড়িতে $13$টা মানে $1$টা — কারণ $13 \equiv 1 \pmod{12}$।

$$a \equiv b \pmod{n} \iff n \mid (a-b)$$

যেমন $17 \equiv 5 \pmod{12}$, কারণ $17-5=12$ এবং $12 \mid 12$। সমতুল্যভাবে, $17$ ও $5$-কে $12$ দিয়ে ভাগ করলে দুজনেরই ভাগশেষ $5$।

মডুলার এরিথমেটিক যোগ ও গুণকে "রক্ষা" করে

যদি $a \equiv b \pmod n$ এবং $c \equiv d \pmod n$, তাহলে —

  • $(a+c) \equiv (b+d) \pmod n$
  • $(a \times c) \equiv (b \times d) \pmod n$

এর মানে, একটি বড় গণনার মাঝপথে যেকোনো সময় মডুলো নিয়ে সংখ্যাকে ছোট রাখা যায় — চূড়ান্ত ফলাফল একই থাকে। এটাই দ্রুত মডুলার এক্সপোনেনশিয়েশনের ভিত্তি, নিচে দেখুন।

২ · দ্রুত মডুলার এক্সপোনেনশিয়েশন (Repeated Squaring)

RSA-এর মতো ক্রিপ্টোগ্রাফিক সিস্টেমে প্রায়ই $a^e \bmod n$ গণনা করতে হয় যেখানে $e$ হতে পারে শত শত বিট লম্বা। $a^e$ প্রথমে সরাসরি গণনা করে তারপর $\bmod n$ নেওয়া অসম্ভব — সংখ্যাটি এত বিশাল হয়ে যাবে যে কোনো কম্পিউটারের মেমরিতেও ধরবে না। সমাধান: প্রতিটি ধাপেই মডুলো নিয়ে নেওয়া, কখনো সংখ্যাকে বড় হতে না দেওয়া।

কৌশলটি $e$-এর বাইনারি প্রতিনিধিত্ব-এর উপর ভিত্তি করে — একে "square-and-multiply" বলা হয়: প্রতি ধাপে ফলাফল বর্গ (square) করা হয় এবং $e$-এর সেই বিট $1$ হলে অতিরিক্ত একবার $a$ দিয়ে গুণ করা হয়, প্রতিটি ধাপে $\bmod n$ নিয়ে। ফলে ধাপের সংখ্যা $e$-এর সমানুপাতিক নয় — মাত্র $O(\log e)$।

Python
# pow(base, exp, mod) হলো Python-এর বিল্ট-ইন দ্রুত মডুলার এক্সপোনেনশিয়েশন —
# এটি অভ্যন্তরীণভাবেই repeated squaring ব্যবহার করে, O(log exp) সময়ে

result = pow(7, 128, 13)
print("7^128 mod 13 =", result)

# তুলনা করুন: সরাসরি 7**128 গণনা করলে একটি বিশাল সংখ্যা হতো,
# কিন্তু pow(7,128,13) সবসময় ছোট, দ্রুত থাকে
print("7**128 কত ডিজিট লম্বা?", len(str(7**128)), "ডিজিট — কিন্তু mod নিলে মাত্র একটি ছোট সংখ্যা!")

# মডুলার ইনভার্স: pow(a, -1, n) — Python 3.8+
a, n = 7, 13
inv = pow(a, -1, n)
print(f"{a}^(-1) mod {n} =", inv)
print("যাচাই: (a * a⁻¹) mod n == 1 ?", (a * inv) % n == 1)

    
pow(7, 128, 13) ফলাফল দেয় $3$ — এবং এটি গণনা করতে Python-এর মাত্র কয়েকটি বর্গ ও গুণের ধাপ লাগে, $128$ বার গুণ করার দরকার নেই। এটাই সেই দক্ষতা যা RSA-কে বাস্তবে ব্যবহারযোগ্য করে তোলে, যদিও তার ঘাতগুলো (real-world $e$, $d$) কয়েকশো ডিজিট লম্বা হতে পারে।

৩ · মডুলার ইনভার্স

একটি সংখ্যা $a$-এর মডুলার ইনভার্স মডুলো $n$ হলো এমন একটি সংখ্যা $a^{-1}$ যেন —

$$a \cdot a^{-1} \equiv 1 \pmod{n}$$

সাধারণ ভগ্নাংশে $a^{-1} = 1/a$, কিন্তু মডুলার জগতে ভাগ বলে সরাসরি কিছু নেই — তার বদলে "গুণিতক ইনভার্স" দিয়ে কাজ চালানো হয়। গুরুত্বপূর্ণ শর্ত: $a^{-1} \bmod n$-এর অস্তিত্ব থাকে শুধু তখনই যখন $\gcd(a,n)=1$ (অর্থাৎ $a$ ও $n$ coprime, L25 থেকে)। এই ইনভার্স বের করা হয় L25-এর Extended Euclidean Algorithm দিয়ে — কারণ $\gcd(a,n)=1$ হলে Bézout's Identity থেকে এমন $x,y$ পাওয়া যায় যেন $ax+ny=1$, অর্থাৎ $ax \equiv 1 \pmod n$ — সুতরাং $x$-ই হলো কাঙ্ক্ষিত মডুলার ইনভার্স।

12/0 1 2 3 4 5 6 7 ১৩টা বাজলে কাঁটা আবার ১-এ যায় — কারণ 13 ≡ 1 (mod 12)
ঘড়ির কাঁটা $12$-এ পৌঁছালে আবার $0$ (বা $1$টা) থেকে শুরু হয় — এটাই মডুলার এরিথমেটিকের সবচেয়ে পরিচিত রূপ।

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।

প্র ০১ মডুলার এরিথমেটিকে সাধারণ ভাগ (division) কেন সরাসরি সংজ্ঞায়িত নয়, অথচ যোগ-বিয়োগ-গুণ ঠিকই কাজ করে?

যোগ, বিয়োগ, গুণ প্রতিটি পূর্ণসংখ্যার জন্যই সংজ্ঞায়িত এবং মডুলার সিস্টেমে "বন্ধ" (closed) থাকে — ফলাফল সবসময় $\{0,1,\ldots,n-1\}$-এর মধ্যেই থাকে। কিন্তু সাধারণ ভাগ $a/b$ পূর্ণসংখ্যার মধ্যে সবসময় সংজ্ঞায়িত নয় (যেমন $5/2$ পূর্ণসংখ্যা নয়)। মডুলার জগতে এই সমস্যা সমাধান হয় ভাগের বদলে গুণিতক ইনভার্স দিয়ে গুণ করে — কিন্তু সেই ইনভার্স সবসময় থাকে না (যখন $\gcd(a,n) \ne 1$)। তাই ভাগকে সরাসরি সংজ্ঞায়িত না করে শর্তসাপেক্ষ ইনভার্সের ধারণা ব্যবহার করা হয়।

প্র ০২ কেন $a^{-1} \bmod n$-এর অস্তিত্ব থাকতে $\gcd(a,n)=1$ হওয়া জরুরি — উদাহরণ দিয়ে বোঝান কেন এটি ব্যর্থ হয় যখন $\gcd \ne 1$।

ধরুন $a=4, n=6$ ($\gcd(4,6)=2 \ne 1$)। $4^{-1} \bmod 6$ খুঁজতে চাইলে আমাদের এমন $x$ চাই যেন $4x \equiv 1 \pmod 6$। কিন্তু $4x$ সবসময় জোড় (even), আর $6$ দিয়ে ভাগ করলে জোড় সংখ্যার ভাগশেষও সবসময় জোড় ($0,2,4$) — কখনো বিজোড় $1$ হতে পারবে না। তাই কোনো $x$ নেই। সাধারণভাবে, $ax \equiv 1 \pmod n$-এর সমাধান থাকে ঠিক তখনই যখন $\gcd(a,n)$ সংখ্যা $1$-কে ভাগ করে — অর্থাৎ $\gcd(a,n)=1$ হতেই হবে।

প্র ০৩ Repeated squaring ছাড়া, সরাসরি $a^e \bmod n$ গণনা করলে বাস্তবে কী সমস্যা হতো — শুধু "ধীর" হওয়া ছাড়া আর কী?

শুধু গতি নয় — বাস্তবিক অসম্ভবতা। RSA-তে $e$ বা $d$-এর মতো ঘাত কয়েকশো বিট লম্বা হতে পারে (যেমন $2^{2048}$-এর কাছাকাছি)। $a^e$ সরাসরি (মডুলো ছাড়া) গণনা করলে ফলাফলে এত বেশি ডিজিট থাকবে যে তা কোনো কম্পিউটারের RAM-এও ধরানো অসম্ভব — সংখ্যাটির আকার সূচকীয় হারে (exponentially) বাড়ে। Repeated squaring প্রতিটি ধাপে $\bmod n$ প্রয়োগ করে সংখ্যাকে সবসময় $n$-এর চেয়ে ছোট রাখে, ফলে গণনা বাস্তবসম্মত থাকে — এটাই RSA-কে সম্ভব করে তোলার প্রকৌশলগত চাবিকাঠি।

অনুশীলন

  1. হাতে হিসাব করুন: $23 \bmod 7$ ও $58 \bmod 7$ হাতে বের করুন এবং দেখুন এরা কি একে অপরের congruent মডুলো $7$ (অর্থাৎ ভাগশেষ কি একই)?

    $23 = 3\times7+2$, তাই $23 \bmod 7 = 2$। $58 = 8\times7+2$, তাই $58 \bmod 7 = 2$। দুজনের ভাগশেষ একই ($2$), তাই $23 \equiv 58 \pmod 7$।

  2. পরীক্ষা করুন: উপরের কোড সেলে pow(3, 200, 11) চালিয়ে ফলাফল দেখুন, তারপর pow(3, -1, 11) দিয়ে মডুলার ইনভার্স বের করে (3 * inv) % 11 == 1 কিনা যাচাই করুন।

    যেহেতু $\gcd(3,11)=1$, ইনভার্স নিশ্চিতভাবে থাকবে। কোড চালালে pow(3,-1,11) এমন একটি সংখ্যা দেবে যেন সেটিকে $3$ দিয়ে গুণ করলে $11$ দিয়ে ভাগ করলে ভাগশেষ ঠিক $1$ হয় — এটিই মডুলার ইনভার্সের সংজ্ঞা।

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

পূর্ববর্তী পাঠ
পাঠ ২৫ · GCD, LCM ও ইউক্লিডিয়ান অ্যালগরিদম