notes

/Home ....
....

svētdiena, 2015. gada 28. jūnijs

Maģiskie skaitļi

  Maģiskie skaitļi (Magic numbers) tiek lietoti programmēšanā. Šeit nerunāšu par konstantēm kā 0xF4240 (viens miljons heksadecimālā pierakstā), vai angļu valodas saīsinājumiem kā 0xDEADBEEF, bet gan skaitļiem, kas parādās algoritmos un programmās, kurās ar tiem tiek kas darīts, bet jēgu saprast ir grūti.
  Reizēm algoritmus, kas sniedz atbildi uz parametrā uzdotu jautājumu, var uzmodelēt kā aritmētisku funkciju:
 1. Reizinām dotos datus ar konstantu skaitli (vai vairākiem), iegūstam starpvērtību
 2. Ņemam vajadzīgo daļu no tās (to var darīt arī bīdot bitus vai caur and, mod) un mums ir atbilde, vai norāde uz statisku masīvu ar atbildēm (kaut lielu datubāzi).

Piemērs:
Funkcija nosaka bināra skaitļa nuļļu skaitu no labās puses. Darbojas ātrāk nekā cikliski pārskatot skaitļa bitus. Brīnumains aritmētisks reizinājums aizstāj ciklus un if-us.

private static final int TrailingZ[] = {
        63,  0, 58,  1, 59, 47, 53,  2,
        60, 39, 48, 27, 54, 33, 42,  3,
        61, 51, 37, 40, 49, 18, 28, 20,
        55, 30, 34, 11, 43, 14, 22,  4,
        62, 57, 46, 52, 38, 26, 32, 41,
        50, 36, 17, 19, 29, 10, 13, 21,
        56, 45, 25, 31, 35, 16,  9, 12,
        44, 24, 15,  8, 23,  7,  6,  5
    };
    
static final int number_Of_Trailing_Zeros(long mask) {
  return
    TrailingZ[(int)(((mask & -mask)*0x07EDD5E59A4E28C2)>>>58)];
    };

  Konkrētā gadījumā 64 skaitļus, reizinot ar maģisku konstanti 0x07EDD5E59A4E28C2, izdodas sakārtot pieaugošā secībā, lai atbildē ņemtu atbilstošo masīva elementu.  (mask & -mask)   atrod pirmo vieninieku no labās puses. >>>58 paņem tikai 6 bitus, ar ko pietiek 64 vērtībām binārā pierakstā.
  Šādi maģiskie skaitļi ir ģenerēti ar programmēšanas palīdzību, veicot pilno pārlasi. Piemeklēti, konkrētā uzdevuma risināšanai. Tas ir reāli, cikliski ņem tik visus [1,2,...0xFFFFFFFFFFFFFFFF ]   un reizina. To nevarēja izdomāt matemātiķi gadsimtus iepriekš. Varbūt nedaudz paveicas, ka tādi skaitļi vispār eksistē un tos izdodas piemeklēt. Reizināšana ar maģisko konstanti dod varbūtējas sakritības, svarīgi ir nepieļaut nepareizos gadījumus, ko jāpārbauda ar pilno pārlasi pirms lieto algoritmā.

  Uzdevumos, kad kaut kas jākonverģē iteratīvi, maģisks skaitlis var būt tā sākotnējā vērtība, kas reāli visātrāk vai vistuvāk sniedz vajadzīgo rezultātu, piemēram skaitlis 0x5f3759df  tiek lietots 1/√x aprēķināšanā

Nav komentāru:

Ierakstīt komentāru