জুলিয়া একটি সাধারণ উদ্দেশ্যে ব্যবহারযোগ্য ভাষা, যা বেশিরভাগ প্রোগ্রামিং কাজে ব্যবহার করা যায়। তবে বাস্তবে এর প্রধান ব্যবহারগুলো মূলত ইঞ্জিনিয়ারিং ও বিজ্ঞানে। দ্রুত, বহুমুখী ও অত্যাধুনিক সংখ্যাগত গণনা এই ভাষার নকশার কেন্দ্রে আছে।
ইন্টিজার হলো একটি "গোল" সংখ্যা, যার কোনো দশমিক বিন্দু থাকে না।
বেসিকস কনসেপ্টে আমরা দেখেছি যে, টাইপ উল্লেখ না করেই একটি ভ্যারিয়েবলে ইন্টিজার মান অ্যাসাইন করা যায়।
পড়ার সুবিধার জন্য আন্ডারস্কোরকে ডিজিট আলাদা করার চিহ্ন হিসেবে ব্যবহার করা যায়। কম্পাইলার এগুলো উপেক্ষা করে।
julia> x = 3
3
julia> typeof(x)
Int64
julia> large_number = 1_234_567_890
1234567890
এটা আর আশ্চর্যের কিছু নয় যে ফ্লোটিং-পয়েন্ট সংখ্যায় একটি দশমিক বিন্দু থাকে, আর বিন্দুর পরে একটি ভগ্নাংশ থাকে।
julia> f = 3.45
3.45
julia> typeof(f)
Float64
অবশ্যই, বৈজ্ঞানিক নোটেশনও সমর্থিত।
julia> avogadro = 6.02e23
6.02e23
সর্বোচ্চ ও সর্বনিম্ন মান দেখে আপনি হয়তো অবাক হতে পারেন:
julia> typemax(Float64)
Inf
julia> typemin(Float64)
-Inf
ইনফিনিটি একটি বৈধ মান!
বেসিকস কনসেপ্টে আলোচনা করা হয়েছে, গাণিতিক অপারেটরগুলো বেশিরভাগ ক্ষেত্রেই ছোটদের শেখানো সাধারণ পাটিগণিতের মতোই কাজ করে।
মনে রাখবেন, সূচকীকরণে ^ ব্যবহার হয়, ** নয় (দুটোই অন্য ভাষায় প্রচলিত)।
2 + 3 # 5 (addition)
2 - 3 # -1 (subtraction)
2 * 3 # 6 (multiplication)
8 / 2 # 4.0 (division)
8 % 3 # 2 (remainder)
2 ^ 3 # 8 (exponentiation)
তবে জুলিয়ার কিছু নিজস্ব বিষয় আলোচনার যোগ্য।
julia> x = 4.2
4.2
julia> 2 * x
8.4
julia> 2x
8.4
julia> 2.4x
10.08
এটা হয়তো অবাক করার মতো।
অন্য বেশিরভাগ কম্পিউটার ভাষার মতোই, *-কে ইনফিক্স অপারেটর হিসেবে ব্যবহার করা সবসময়ই সম্ভব।
কিন্তু যাঁরা জুলিয়া তৈরি করেছেন, তাঁরা মনে করেন কোড যতটা সম্ভব গাণিতিক সমীকরণের মতো হওয়া উচিত।
যেহেতু ভ্যারিয়েবলের নাম অবশ্যই একটি অক্ষর দিয়ে শুরু হতে হয়, তাই নামের আগে একটি সংখ্যা (ইন্টিজার বা ফ্লোটিং-পয়েন্ট) বসালে সেটি অন্তর্নিহিত গুণ হিসেবে ধরে নেওয়া হয়।
উদাহরণস্বরূপ, একটি গোলকের পৃষ্ঠতলের ক্ষেত্রফল বের করতে চাইলে 4 * pi * r * r-এর বদলে আমরা এভাবে লিখতে পারি:
julia> surface(r) = 4π * r^2
surface (generic function with 1 method)
julia> surface(3)
113.09733552923255
যদিও π একটি বিল্ট-ইন ধ্রুবক, এটি আসলে একটি (গ্রিক) অক্ষরও বটে।
তাই π-কে r থেকে আলাদা করতে পার্সারের এখনও একটি স্পষ্ট * দরকার হয়।
ইনফিক্স অপারেটর হিসেবে / ব্যবহার করলে সবসময়ই ফ্লোটিং-পয়েন্ট ফলাফল পাওয়া যায়, এমনকি ইন্টিজার ইনপুটের ক্ষেত্রেও।
ইন্টিজার ভাগের জন্য আরও কিছু উপায় আছে।
julia> 10 / 3 # floating-point division
3.3333333333333335
julia> div(10, 3) # integer division
3
julia> 10 ÷ 3 # synonym for div()
3
julia> 10 // 3 # rational number (fraction)
10//3
div() ফাংশনটি ইন্টিজার ভাগের জন্য, যেখানে ফলাফল শূন্যের দিকে ছেঁটে দেওয়া হয়: ধনাত্মক সংখ্যার ক্ষেত্রে নিচের দিকে, ঋণাত্মক সংখ্যার ক্ষেত্রে উপরের দিকে।
সমার্থক হিসেবে আমরা ইনফিক্স অপারেটর ÷ ব্যবহার করতে পারি, যা আবারও এটিকে গাণিতিক দেখানোর চেষ্টা।
আপনি যদি জুলিয়া-সচেতন এডিটর ব্যবহার করেন, তাহলে \div টাইপ করে <Tab> চাপুন।
// অপারেটরটি এই কনসেপ্টের পরিধির বাইরে।
আপাতত আমরা শুধু বলতে পারি, //-এর ফলাফল একটি "রেশনাল" সংখ্যা, যেটিকে বেশিরভাগ মানুষ ভগ্নাংশ বলে।
এটি প্রায়ই স্বয়ংক্রিয়ভাবে ঘটে থাকে:
julia> x = 2 + 3.5
5.5
julia> typeof(x)
Float64
আমরা একটি Int64-এর সাথে একটি Float64 যোগ করেছি, আর ফলাফল পেয়েছি Float64।
আসলে যোগ করার আগেই ইন্টিজারটি নিঃশব্দে Float64-এ রূপান্তর করা হয়েছিল।
ফ্লোট থেকে ইন্টিজার রূপান্তর অনিবার্যভাবে আরও জটিল। দশমিক বিন্দুর পরের অংশ নিয়ে আপনি কী করতে চান?
round() ফাংশনটি নিকটতম পূর্ণসংখ্যায় রূপান্তর করে, আর 4.5-এর মতো সমান দূরত্বের ক্ষেত্রে নিকটতম জোড় পূর্ণসংখ্যায় রাউন্ড করে।floor() নিচের দিকে রাউন্ড করে, ceil() উপরের দিকে, আর trunc() শূন্যের দিকে।Int32() দিয়ে, একটি InexactError এরর হবে।তবে ডিফল্টভাবে এই ফাংশনগুলো আপনার কাঙ্ক্ষিত ইন্টিজার টাইপ রিটার্ন করে না। আপনি চাইলে আউটপুটের টাইপ নির্দিষ্ট করে দিতে পারেন।
julia> round(4.5)
4.0
julia> ceil(Int, 4.3)
5
digits কিওয়ার্ড ব্যবহার করে দশমিক বিন্দুর পরে নির্দিষ্ট সংখ্যক ডিজিটে রাউন্ড করাও সম্ভব।
julia> round(π, digits=10)
3.1415926536
নিশ্চয়ই এতে শুধু একটি এরর হয়? আসলে ব্যাপারটা তত সহজ নয়।
আপনি যেমন আশা করতে পারেন, ÷ বা // দিয়ে ইন্টিজার ভাগ করলে এরর হয়।
/ দিয়ে ফ্লোটিং-পয়েন্ট ভাগ করলে সাধারণ কম্পিউটার সায়েন্সের বদলে ইঞ্জিনিয়ারিংয়ের মতো একটা দৃষ্টিভঙ্গি নেওয়া হয়:
julia> 2 / 0
Inf
julia> 0 / 0
NaN
আগের একটি অংশে আলোচনা করা হয়েছে, জুলিয়ায় ইনফিনিটি একটি বৈধ ফ্লোটিং-পয়েন্ট সংখ্যা, যা Inf দিয়ে প্রকাশ করা হয়।
লবও যদি শূন্য হয়, তাহলে ফলাফলটি গাণিতিকভাবে অসংজ্ঞায়িত।
তখন জুলিয়া এটিকে "সংখ্যা নয়" হিসেবে ধরে, যা NaN দিয়ে প্রকাশ করা হয়।
আপনার বন্ধু Chandler বিশ্বজুড়ে নানা বিচিত্র দেশ ঘুরে দেখার পরিকল্পনা করছেন। দুঃখজনকভাবে Chandler-এর গণিতের দক্ষতা তেমন ভালো নয়। ভ্রমণের সময় মুদ্রা বিনিময়ে প্রতারিত হওয়ার ব্যাপারে তিনি বেশ চিন্তিত, আর তাই তিনি চান আপনি তাঁর জন্য একটি মুদ্রা ক্যালকুলেটর বানিয়ে দেন। অ্যাপটির জন্য তাঁর স্পেসিফিকেশনগুলো এই রকম:
exchange_money() ফাংশনটি তৈরি করুন, যেটি ২টি প্যারামিটার নেয়:
budget : আপনি যে পরিমাণ অর্থ বিনিময় করার পরিকল্পনা করছেন।exchange_rate : বিদেশি মুদ্রার এক এককের সমান দেশীয় মুদ্রার পরিমাণ।এই ফাংশনটি বিনিময় করা মুদ্রার মান রিটার্ন করবে।
নোট: আপনার মুদ্রা যদি USD হয় এবং আপনি 1.20 বিনিময় হারে USD-এর বিনিময়ে EUR নিতে চান, তাহলে 1.20 USD == 1 EUR।
julia> exchange_money(127.5, 1.2)
106.25
get_change() ফাংশনটি তৈরি করুন, যেটি ২টি প্যারামিটার নেয়:
budget : বিনিময়ের আগে অর্থের পরিমাণ।exchanging_value : বিনিময়ের জন্য বাজেট থেকে যে পরিমাণ অর্থ নেওয়া হয়।এই ফাংশনটি বাজেট থেকে যে পরিমাণ অর্থ অবশিষ্ট থাকে তা রিটার্ন করবে।
julia> get_change(127.5, 120)
7.5
get_value_of_bills() ফাংশনটি তৈরি করুন, যেটি ২টি প্যারামিটার নেয়:
denomination : একটি একক নোটের মান।number_of_bills : মোট নোটের সংখ্যা।এই বিনিময় বুথটি কেবল নির্দিষ্ট এককে নগদ অর্থে লেনদেন করে। আপনি যে মোট অর্থ পাবেন তা অবশ্যই একটি "নোট" বা এককের মান দিয়ে বিভাজ্য হতে হবে, আর এই ভাগে ভগ্নাংশ বা অবশিষ্ট অংশ থেকে যেতে পারে। আপনার ফাংশনটি কেবল সেই নোটগুলোর মোট মান রিটার্ন করবে (ভগ্নাংশ বাদ দিয়ে) যা বুথটি ফেরত দেবে। দুঃখজনকভাবে, বাকি অংশটি বুথটি বাড়তি বোনাস হিসেবে রেখে দেয়।
julia> get_value_of_bills(5, 128)
640
get_number_of_bills() ফাংশনটি তৈরি করুন, যেটি amount ও denomination নেয়।
এই ফাংশনটি প্রদত্ত amount-এর মধ্যে আপনি কতগুলো মুদ্রা নোট পেতে পারেন তার সংখ্যা রিটার্ন করবে। অন্যভাবে বললে: শুরুর পরিমাণে কতগুলো সম্পূর্ণ নোট ধরে? মনে রাখবেন, আপনি কেবল সম্পূর্ণ নোট পেতে পারেন, নোটের ভগ্নাংশ নয়, তাই সেই অনুযায়ী ভাগ করতে ভুলবেন না। আসলে আপনি নিকটতম সম্পূর্ণ নোট/এককে নিচের দিকে রাউন্ড করছেন।
julia> get_number_of_bills(127.5, 5)
25
get_leftover_of_bills() ফাংশনটি তৈরি করুন, যেটি amount ও denomination নেয়।
এই ফাংশনটি নোটের একক অনুযায়ী আপনার শুরুর amount থেকে যে অবশিষ্ট পরিমাণ ফেরত দেওয়া যায় না তা রিটার্ন করবে। বুথটি ঠিক কতটুকু রেখে দেয় তা জানা খুবই গুরুত্বপূর্ণ।
julia> get_leftover_of_bills(127.5, 20)
7.5
exchangeable_value() ফাংশনটি তৈরি করুন, যেটি budget, exchange_rate, spread ও denomination নেয়।
spread প্যারামিটারটি বিনিময় ফি হিসেবে নেওয়া শতকরা হার, যা একটি ইন্টিজার হিসেবে লেখা হয়।
এটিকে 100 দিয়ে ভাগ করে দশমিকে রূপান্তর করতে হবে।
যদি 1.00 EUR == 1.20 USD হয় এবং spread হয় 10, তাহলে মোট বিনিময় হার আসলে হবে: 1.00 EUR == 1.32 USD, কারণ 1.20-এর 10% হলো 0.12, আর এই অতিরিক্ত ফি বিনিময়ের সাথে যোগ হয়।
এই ফাংশনটি বিনিময় হার-এর সাথে spread যোগ করে হিসাব করার পর নতুন মুদ্রার সর্বোচ্চ মান রিটার্ন করবে। মনে রাখবেন, মুদ্রার একক একটি সম্পূর্ণ সংখ্যা, যা আর ভাগ করা যায় না।
নোট: রিটার্ন ভ্যালুটি ইন্টিজার টাইপের হওয়া উচিত।
julia> exchangeable_value(127.25, 1.20, 10, 20)
80
julia> exchangeable_value(127.25, 1.20, 10, 5)
95
Exercism-এ সাইন আপ করুন, Julia ট্র্যাকের 35টি কনসেপ্ট128টি অনুশীলনী আর সত্যিকারের মানুষের মেন্টরিং দিয়ে শিখুন ও দক্ষ হয়ে উঠুন, সম্পূর্ণ বিনামূল্যে।