2.4
— Integers
एक integer (या integral)
type variable, ऐसा variable होता है जो केवल non-fractional numbers या पूर्णांक संख्याएँ ही store कर सकता है (जैसे -2, -1, 0, 1, 2) । C++ में हमारे इस्तेमाल
के लिए five अलग-अलग fundamental integer types उपलब्ध हैं:
|
Category
|
Type
|
Minimum Size
|
Note
|
|
character
|
char
|
1
byte
|
|
|
integer
|
short
|
2
bytes
|
|
|
int
|
2
bytes
|
ज्यादातर
modern computers में 4
|
|
|
long
|
4
bytes
|
||
|
long
long
|
8
bytes
|
C99/C++11
type
|
इनमे से char एक महत्वपूर्ण data type है जो बाकी integers से थोडा अलग है, इसलिए इसे character और integer, दोनों categories
में रखा जा सकता है । आगे के lessons में हम char के विशेष होने का कारण जानेंगे । इस lesson में आप इसे integer मान सकते हो ।
अलग-अलग integer types होने का सबसे महत्वपूर्ण कारण है, उनके sizes का अलग-अलग होना -- integer जितनी बड़ी size का होगा, वो उतनी ही बड़ी संख्या (numbers) store कर पायेगा । ध्यान दे की C++ केवल इस बात की guarantee देता है की integers के sizes कम-से-कम कितने हो सकते हैं, C++ ये कभी नहीं कहता की कोई integer अधिकतम कितना बड़ा हो सकता है । किसी variable के size का पता कैसे लगाये, ये जानने के लिए lesson 2.3 -- variable sizes and the sizeof operator पर एक नज़र डाले ।
अलग-अलग integer types होने का सबसे महत्वपूर्ण कारण है, उनके sizes का अलग-अलग होना -- integer जितनी बड़ी size का होगा, वो उतनी ही बड़ी संख्या (numbers) store कर पायेगा । ध्यान दे की C++ केवल इस बात की guarantee देता है की integers के sizes कम-से-कम कितने हो सकते हैं, C++ ये कभी नहीं कहता की कोई integer अधिकतम कितना बड़ा हो सकता है । किसी variable के size का पता कैसे लगाये, ये जानने के लिए lesson 2.3 -- variable sizes and the sizeof operator पर एक नज़र डाले ।
Integers को define करना
नीचे कुछ integers define किये गये हैं:
|
1
2
3
4
5
6
7
8
|
char c;
short int si; // सही
short s; //
सबसे अच्छा
int i;
long int li; // सही
long l; // सबसे अच्छा
long long int lli; // सही
long long
ll; // सबसे अच्छा
|
Integers
define करते वक़्तshort int, long
int, और long
long int लिखना भी सही है,लेकिन फिर भी इनके छोटे रूप short, long,
और long
long का इस्तेमाल करना बेहतर रहेगा । इनका
प्रयोग करना typing में मेहनत बचाता है
और साथ ही लम्बे नामो में int लगाकर उनका प्रयोग करना, उस type को बाकी int
variables से अलग करके पहचान सकना मुश्किल बनाता
है । यदि आप short या long
modifiers लिखना भूल गये हैं, तो ये मुश्किलें कड़ी कर सकता है ।
Integers को पहचानना
क्यूंकि char, short, int, और long के sizes आपके compiler या/और computer पर निर्भर करते हैं और उनके बदलने पर ये (इनके sizes) भी बदल सकते हैं, इसलिए integers को उनके नाम के बजाय उनके size के आधार पर पहचानना ज्यादा सही रहेगा । हम integers को memory में उनके द्वारा allocate किये गये bits की संख्या से पहचानने की सलाह देते हैं (जैसे “32-bit
integer” ना की”long”).
Integer
ranges और उनके sign
जैसा की आपने पिछले section में सिखा, n bits का एक variable 2n अलग-अलग values store कर सकता है । लेकिन, कैसे values? एक data-type,
values के एक समूह को store करने में सक्षम है, जिसे उस data-type का range खा जाता है । किसी integer
variable का range दो दो कारकों पर निर्भर करता है: इसका size
(bits में), और इसका sign, जो”signed” या “unsigned”
हो सकता है ।
A एक signed integer एक ऐसा variable है जो negative (ऋणात्मक) और positive (धनात्मक), दोनों तरह के values
store कर सकता है । किसी variable को “signed” declare करने के लिए आपsigned keyword
का इस्तेमाल कर सकते हैं:
|
1
2
3
4
5
|
signed char c;
signed short s;
signed int i;
signed long l;
signed long long ll;
|
पहले से ही, keyword signed को variable के data-type
के आगे लिखना सही माना गया है ।
किसी 1-byte signed integer का range -128 से 127 तक होता है । -128 और 127 (इन दोनों को
मिलाकर) के बीच का कोई भी value किसी 1-byte signed integer variable में बिना किसी दिक्कत के store किया जा सकता है ।
कभी-कभी हमें पहले से पता होता है की हमे किसी variable में negative numbers store करने की ज़रूरत नहीं पडने वाली है । जब आप आकार या परिमाण जैसे किसी
इकाई (जैसे 10 meter या 5
bottles) को variable में store करते हैं, तो संभवतः आपको negative numbers की ज़रूरत नहीं पड़ेगी । एक unsignedinteger ऐसा integer है जो सिर्फ positive
value ही store कर सकता है । एक variable को unsigned declare करने के लिए हम unsigned keyword
का प्रयोग करते हैं :
|
1
2
3
4
5
|
unsigned char c;
unsigned short s;
unsigned int i;
unsigned long l;
unsigned long long ll;
|
एक 1-byte के unsigned
integer का range 0 से 255 तक होता है ।
ध्यान दीजिये की एक variable को unsigned declare करने का मतलब है की
अब ये negative values store नहीं कर पायेगा, लेकिन positive value की बात करे तो एक unsigned variable signed
variable से लगभग दो गुणा बड़ा value
store कर सकता है ।
अब आप signed और unsigned के बीच अंतर को समझ
गये हो, तो आइये अब उनके ranges पर एक नज़र डाले:
|
Size/Type
|
Range
|
|
1
byte signed
|
-128
to 127
|
|
1
byte unsigned
|
0
to 255
|
|
2
byte signed
|
-32,768
to 32,767
|
|
2
byte unsigned
|
0
to 65,535
|
|
4
byte signed
|
-2,147,483,648
to 2,147,483,647
|
|
4
byte unsigned
|
0
to 4,294,967,295
|
|
8
byte signed
|
-9,223,372,036,854,775,808
to 9,223,372,036,854,775,807
|
|
8
byte unsigned
|
0
to 18,446,744,073,709,551,615
|
जिनका math अच्छा है, उनके लिए एक shortcut,
n-bit के एक signed
variable का range -(2n-1)
से 2n-1-1
तक होता है । n-bit के एक unsigned variable का range (2n)-1 होता है । जिनका math अच्छा नहीं है, वो तुपर वाले table का use करे :)
नए programmers कभी-कभी signed और unsigned को एक ही समझ बैठते
हैं । उनके बीच के अंतर को अछे से समझने के लिए ध्यान दे: negative
numbers को positive
numbers से अलग दिखाने के लिए हम एक minus
sign (-) का use करते हैं । यदि कोई sign नहीं दिया गया है (जैसे की 5, 6, 8), तो इसका मतलब है की number positive है । ठीक उसी तरह, एक integer जिसका sign है (एक signed integer) वो negative और positive के बीच में डिफरेंस बता सकता है । बिना sign का integer (unsigned integer) का मतलब है इसपे आ सकने वाले सरे values
positive हैं ।
Default
signs और integer
best practices
तो ज़रा सोचिये, क्या होगा यदि हम किसि variable को signed या unsigned
declare न करे ?
|
Category
|
Type
|
Default Sign
|
Note
|
|
character
|
char
|
Signed
या Unsigned
|
अकसर
signed
|
|
integer
|
short
|
Signed
|
|
|
int
|
Signed
|
||
|
long
|
Signed
|
||
|
long
long
|
Signed
|
char को छोड़कर सरे integer variable by default
signed होते हैं । Char का कुछ भी निश्चित नहीं है । वो by
default signed या unsigned,
दोनों हो सकता है (लेकिन अधिकतर ये signed ही होता है ) ।
सामान्यतः, signed keyword का इस्तेमाल नहीं किया जाता है (क्यूंकि इसकी कोई ज़रुरत नहीं होती) ।
लेकिन char variables में इसकी ज़रूरत
होती है (यदि किसी char को signed होने ज़रूरत है और by default ये signed नहीं है) ।
programming
में सबसे बढ़िया यही है की जहां तक हो
सके unsigned keyword का इस्तेमाल ना ही किया जाये जब तक unsigned
variable की बहुत ज्यादा ज़रूरत नहीं है । ऐसा
इसलिए, क्यूंकि unsigned
integers के प्रयोग से unexpected
bugs रह जाने के चांसेस बढ़ जाते हैं ।
Rule:
unsigned integers की जगह signed
integers का ही इस्तेमाल करे जब तक unsigned
integers की बहुत ज्यादा ज़रूरत न हो ।
Overflow
क्या होगा यदि हम किसी variable के data type के range से बाहर का कोई value variable में store करना चाहे ? Overflow,
जी हाँ । Overflow तब होता है जब value को store करने के लिए आवश्यक
memory नहीं होती और value के bits गायब हो जाते हैं ।
Lesson 2.1 -- Basic addressing और variable declaration में हमने बताया था की data binary format में store होते हैं ।
Binary
(base 2) में सिर्फ दो digit
allowed होते हैं, 0 या 1 । 0 से 15 तक binary में कुछ इस तरह से लिखा जाता है :
|
Decimal Value
|
Binary Value
|
|
0
|
0
|
|
1
|
1
|
|
2
|
10
|
|
3
|
11
|
|
4
|
100
|
|
5
|
101
|
|
6
|
110
|
|
7
|
111
|
|
8
|
1000
|
|
9
|
1001
|
|
10
|
1010
|
|
11
|
1011
|
|
12
|
1100
|
|
13
|
1101
|
|
14
|
1110
|
|
15
|
1111
|
जैसा की आप देख सकते हो, बड़े numbers को ज्यादा bits की ज़रूरत होती है । हमारे variables में number of bits निश्चित होते हैं
और इसलिए किसी variable में उसके range से बाहर का कोई value store करने पर overflow होता है ।
Overflow के उदाहरण
4 bit के एक unsigned variable की कल्पना कीजिये । ऊपर दिए गए table में जितने भी numbers हैं, वो इस variable में फिट हो जायेंगे क्यूंकि उनमे से कोई भी 4 bit से ज्यादा का नहीं है ।
लेकिन क्या होगा यदि हम 4 bit से ज्यादा bits वाले number को इस 4 bit वाले variable में store करना चाहे तो ? जैसा की पहले बताया जा चूका है, यहाँ overflow होगा और सबसे कम significant
(दाहिनी ओर के) bits को छोड़कर बाकी बचे bits खो जायेंगे ।
एक example के तौर पर, यदि हम डेसीमल value 21 को 4-bit के variable में रखना चाहे, तो 21 के bits खो जायेंगे:
|
Decimal Value
|
Binary Value
|
|
21
|
10101
|
21 को binary में represent
करने के लिए 5 bits चाहिए(10101) । दाहिनी ओर के 4 bits (0101) variable में बचे रहेंगे और
बाकी (1) खो जायेंगे । Overflow के कारण अब ये variable 0101 को represent
करेगा जो साल में 5 का binary code है ।
Note: अभी तक यदि आपको decimal से binary या binary से decimal conversion नहीं आता, तो कोई बात नहीं हम इसकी अपेक्षा भी नहीं रखते । इसके बारे में हम 3.7 -- Converting between binary and
decimal वाले लेस्सिओं में
जानेंगे ।
आइये अब code वाला एक उदाहरण देखते हैं । मान लिया की हमारे machine में short 16 bits का है:
|
1
2
3
4
5
6
7
8
9
10
11
|
#include <iostream>
int main()
{
using namespace std;
unsigned short x =
65535; // 16-bit का सबसे बड़ा unsigned
value
cout << "x
was: " << x << endl;
x = x + 1; // 65536
variable x के range के बाहर का है -- overflow हो जायेगा क्यूंकि x ज्यादा-से-ज्यादा 16 bits के ही value store कर सकता है
cout << "x
is now: " << x << endl;
return 0;
}
|
क्या लगता है आपको, इस program का output क्या होना चाहिए?
x was: 65535
x is now: 0
क्या हुआ? हमने variable को overflow कर दिया है क्यूंकि
हमने इस variable में इसके range के बाहर का एक value (65536) store करने की कोशिश की । हुआ यूँ, की अब हमारा variable range में आने वाले सबसे छोटे value को store कर रहा है ।
|
Advanced
readers के लिए, असल
में यहाँ कुछ ऐसा हो रहा है: number
65,535 का binary bit pattern कुछ ऐसा है 1111 1111 1111 1111 । 2 byte
(16-bit) के unsigned variable में आ सकने वाला 65,535
सबसे बड़ा value है
और इसलिए इस number को represent
करने के लिए सारे 16-bits use होते
हैं । 65,536 को binary में कुछ इस तरह represent
किया जाता है: 1 0000
0000 0000 0000 । आप देख सकते हो,
65,536 में 17-bits हैं!
इसलिए, सबसे बायीं ओर वाला bit
(जो 1 है)
overflow के कारण गायब हो जाता है और दायी ओर के 16 bits बच
जाते हैं । बचे हुए bit
pattern (0000 0000 0000 0000) का
decimal value zero (0) है और इसलिए ये output
में आय ।
|
इसी तरह, हम range के नीचले हिस्से को भी overflow कर सकते हैं जिसके कारण output range का सबसे बड़ा value होगा ।
|
1
2
3
4
5
6
7
8
9
10
11
|
#include <iostream>
int main()
{
using namespace std;
unsigned short x = 0;
// 2-byte का सबसे छोटा unsigned
value
cout << "x
was: " << x << endl;
x = x - 1; //
overflow!
cout << "x
is now: " << x << endl;
return 0;
}
|
x was: 0
x is now: 65535
Overflow के होने से data lost हो जाता है, जो की शायद कोई कभी
नहीं चाहेगा । यदि आपको कभी भी लगे की इस variable में दिए गए data type के range के बाहर का value भी store किया जा सकता है, तो ज्यादा बड़ा variable ही use करे ।
और एक बात ध्यान दीजिये की overflow के results हम तभी guess कर सकते हैं जब दिया गया variable एक unsigned integer हो । Signed
integers या non-integers
(जैसे की floating
point numbers) के overflow होने पर results अलग-अलग machines में अलग-अलग हो सकते हैं ।
Rule: कभी भी, कभी भी overflow से होने results पर भरोसा कर कोई code न लिखे ।.
Integer
division
जब दो integers को divide किया जाता है, तो C++ आपके सोचे अनुसार results देता है यदि divide करने पर आने वाला result (भागफल) भी खुद integer हो:
|
1
2
3
4
5
6
7
|
#include <iostream>
int main()
{
std::cout << 20
/ 4;
return 0;
}
|
इसका result वही है जो आप सोच
रहे हो:
5
लेकिन तब क्या होगा जब integers को divide करने पर एक fractional
value मिले:
|
1
2
3
4
5
6
7
|
#include <iostream>
int main()
{
std::cout << 8 /
5;
return 0;
}
|
ये वाला थोडा अज़ीब result देगा:
1
तो बात ये है, जब दो integers को लेकर division किया जा रहा हो, तो result भी integer ही होगा और क्यूंकि integers में कोई fractional part नहीं होता, दशमलव (decimal
‘.’) के बाद आने वाला value गायब हो जाता है (और हाँ, कोई rounding नहीं होता)।
अब ऊपर वाले example पे एक नज़र डालते हैं, 8 / 5 को भाग देने पर 1.6 मिलता है । Fractional part (0.6) गायब हो जाता है और result में सिर्फ 1 बचता है ।
Rule:
integer division perform करते वक़्त थोडा
सावधान रहे क्यूंकि आपके पास कोई fractional part नहीं बचता और इस तरह से division
accurate नहीं भी हो सकता है ।
|

No comments:
Post a Comment