Հիմա ուզում եմ խոսել այն մասին, թե ինչպես կառուցել թվի երկուական ներկայացումը, երբ լեզվում տողերի կցման հնարավորություն չկա, և արդյունքը պետք է գրել սիմվոլների բուֆերի մեջ։ Ընդունված մեթոդն այն է, որ տրված տասական թիվը, քանի դեռ այն զրո չի դարձել, հաջորդաբար բաժանվում է `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