Kirjautuminen

Haku

Tehtävät

Keskustelu: Koodit: C: Laske bitit

kala [12.06.2003 19:33:47]

#

Tällä funktiolla voit laskea, montako ykkösbittiä 32-bittisessä kokonaisluvussa on.

int count_bits(unsigned long i)
{
      i = ((i & 0xAAAAAAAAUL) >>  1) + (i & 0x55555555UL);
      i = ((i & 0xCCCCCCCCUL) >>  2) + (i & 0x33333333UL);
      i = ((i & 0xF0F0F0F0UL) >>  4) + (i & 0x0F0F0F0FUL);
      i = ((i & 0xFF00FF00UL) >>  8) + (i & 0x00FF00FFUL);
      i = ((i & 0xFFFF0000UL) >> 16) + (i & 0x0000FFFFUL);
      return (int)i;
}

FooBat [04.02.2019 23:01:20]

#

Tämä on vähän vanha vinkki, mutta jos on mielenkiintoa bittikikkailuun kannattaa lukaista helmiä täältä: https://graphics.stanford.edu/~seander/bithacks.html

Tuolla esimerkiksi on tuon ykkösbittien laskennan 'optimoitu' versio.

unsigned int v; // count bits set in this (32-bit value)
unsigned int c; // store the total here
...
v = v - ((v >> 1) & 0x55555555);                    // reuse input as temporary
v = (v & 0x33333333) + ((v >> 2) & 0x33333333);     // temp
c = ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; // count

Ja sitten tietenkin, jos tällä on oikeasti tarvetta nopeuteen, kannattaa käyttää tutustua kääntäjä spesifisiin intirinsic käskyihin kuten Microsoftilla __popcnt ja __builtin_popcount clang/gcc.

Kannattaa tutustua myös https://godbolt.org/ sivustoon, jolla voi testailla helposti minkälaista konekoodia kirjoittamasi koodi tuottaa. Esim. on jännä havaita, että clang ainakin tietyillä asetuksilla tuottaa __builtin_popcount käskyllä tuon saman koodin joka on tuossa ylempänä esitetty. Toisaalta tuon saanee tuottamaan myös sen yksittäisen popcnt konekäskyn, jos kääntäjälle antaa oikeat parametrit (ja sanoo, että laite tukee käskyä).

Grez [11.03.2021 13:09:51]

#

Jos oletetaan että bittejä on vähän, niin myös tällainen toimii suht nopeasti lähtökohtaisesti minkä vaan kokoiselle kokonaisluvulle.

int popCount (U64 x) {
   int count = 0;
   while (x) {
       count++;
       x &= x - 1;
   }
   return count;
}

jlaire [11.03.2021 16:30:31]

#

Tuo Grezin toteutus on hyvä myös siksi, että kääntäjät osaavat korvata sen popcnt:lla jos se on käytössä: https://godbolt.org/z/cMzn4v

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta