মডুলার এরিথমেটিক
এই পাঠে যা শিখবেন
- 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)$।
# 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$-ই হলো কাঙ্ক্ষিত মডুলার ইনভার্স।
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।
প্র ০১ মডুলার এরিথমেটিকে সাধারণ ভাগ (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-কে সম্ভব করে তোলার প্রকৌশলগত চাবিকাঠি।
অনুশীলন
-
হাতে হিসাব করুন: $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$।
-
পরীক্ষা করুন: উপরের কোড সেলে
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-এ আপনার পরবর্তী পদক্ষেপ
- কোর্সের সম্পূর্ণ সিলেবাস দেখুন ৪৪টি পাঠ M5-এর বাকি পাঠগুলো — ফার্মা/ইউলার'স থিওরেম, RSA — এই মডিউলেই আছে।
- পাঠ ২৭ · ফার্মার লিটল থিওরেম ও অয়লার'স থিওরেম পরবর্তী পাঠ মডুলার এরিথমেটিকের উপর ভিত্তি করে RSA-এর প্রকৃত গাণিতিক ভিত্তি।
- পাঠ ২৫ · GCD, LCM ও ইউক্লিডিয়ান অ্যালগরিদম আগের পাঠ Extended Euclidean Algorithm — মডুলার ইনভার্স বের করার হাতিয়ার।