Հիմա ուզում եմ խոսել այն մասին, թե ինչպես կառուցել թվի երկուական ներկայացումը, երբ լեզվում տողերի կցման հնարավորություն չկա, և արդյունքը պետք է գրել սիմվոլների բուֆերի մեջ։ Ընդունված մեթոդն այն է, որ տրված տասական թիվը, քանի դեռ այն զրո չի դարձել, հաջորդաբար բաժանվում է `2`֊ի, և բաժանումից ստացված մնացորդները գրառվում են հակառակ կարգով։ Այստեղ խնդիրն այն է, որ կամ պետք է հենց սկզբից մնացորդները բուֆերի մեջ գրառել հակառակ հաջորդականությամբ՝ նախապես իմանալով երկուական տեսքի զբաղեցրած նիշերի քանակը, կամ մնացորդները գրառել դրանց ստացվելու ուղիղ հաջորդականությամբ և վերջում վերադասավորել հակառակ կարգով։ Թվի երկուական տեսքի զբաղեցրած նիշերի քանակը կարելի է ստանալ լոգարիթմի օգնությամբ․ \(length=\lceil\log_2{n}\rceil\)
// տարբերակ I
void bin_a( int num, char* res )
{
size_t length = log(num)/log(2);
while( num ) {
res[length--] = "01"[num & 0x01];
num >>= 1;
}
}
// տարբերակ II
void bin_b( int num, char* res )
{
char* p = res;
while( num ) {
*p++ = "01"[num & 0x01];
num >>= 1;
}
while( p > res ) {
char t = *(--p);
*p = *res;
*res = t;
++res;
}
}
Թե զբաղեցնելիք նիշերի քանակը, և թե մնացորդները հակառակ գրելուց հետո դրանք շրջելը ես համարում եմ ավելորդ աշխատանք։ Ստորև ցուցադրում եմ մի եղանակ, որում թվի տասական տեսքից երկուական տեսքի կառուցումը կատարվում է առանց վերը նշված «ավելորդ» (կամ ոչ ցանկալի) գործողությունների։Եվ այսպես,
int bin( int num, char* res ) ֆունկցիան արգումենտում ստանում է ձևափոխվելիք թիվը և արդյունքը գրառելու տեղը (նիշերի բուֆեր), իսկ վերադարձնում է երկուական ներկայացման նիշերի քանակը։ Սա ինտերֆեյսը։ Իսկ իրականացումը ռեկուրսիվ է․ բազա) եթե num֊ը փոքր է 2֊ից, ապա բուֆերի սկզբում գրել '0' կամ '1' համապատասխան նիշը, քայլ) եթե num֊ը մեծ է կամ հավասար երկուսի, ապա bin() ֆունկցիան ռեկուրսիվ կանչել num / 2 քանորդով ու ստանալ len թիվը, որը բուֆերում այդ քանորդի զբաղեցրած նիշերի քանակն է, ապա բուֆերի len + 1 դիրքում գրել num % 2 մնացորդին համապատասխան '0' կամ '1' նիշը։ Ռեկուրսիայի բազային ճյուղում որպես արդյունք ֆունկցիան պետք է վերադարձնի 1, քայլի ճյուղում՝ len + 1։Ահա իրականացումը C լեզվով․
int bin( int num, char* res )
{
if( num < 2 ) {
*res = "01"[num];
return 1;
}
int len = bin(num >> 1, res);
*(res + len) = "01"[num & 0x01];
return 1 + len;
}
Նկարագրված երեք ֆունկցիաների արդյունքները համեմատելու համար օգտագործում եմ test_bin() ֆունկցիան․
bool test_bin( int num )
{
char res_a[32] = { 0 };
bin_a(num, res_a);
char res_b[32] = { 0 };
bin_b(num, res_b);
char res[32] = { 0 };
bin(num, res);
bool pass = 0 == strcmp(res, res_a);
pass = pass && (0 == strcmp(res, res_b));
if( !pass )
printf("| num = %d\tres = %s\tres_a = %s\tres_b = %s\n",
num, res, res_a, res_b);
else
printf("| num = %d\tres= %s\n", num, res);
return pass;
}
concise and neat !!!
ReplyDelete