-- Let's employ regexp and replace
-- the hex values by their count
SELECT n
, NVL(
LENGTH(
REGEXP_REPLACE(
TO_CHAR(n, 'FMXXXXXXXX')
, '([1248]*)([3569AC]*)([7BDE]*)([F]*)[0]*'
, '\1\2\2\3\3\3\4\4\4\4')
)
, 0
) cnt
FROM tbl
/
-- [([1248]*) and \1 can be removed because
-- it is 1 to 1 character replacement, so
-- check this out
SELECT REGEXP_REPLACE(
'8F13247F7018'
, '([3569AC]*)([7BDE]*)([F]*)[0]*'
, '\1\1\2\2\2\3\3\3\3') cnt
FROM dual
/
-- This uses a dynamically built table and
-- replaces hex values by count of bits, as
-- you can see the principle is the same as
-- above in regexp implementation
-- Update 06/25/2005:
-- The code was changed a bit it's Ok not to
-- replace 1,2,4,8 and leave them as is.
SELECT NVL(
LENGTH(
REPLACE(REPLACE(REPLACE(
TRANSLATE(TO_CHAR(n, 'FMXXXXXXXX')
, '35679ABCDEF0'
, '...,..,.,,:'
/* '22232232334' */
)
, '.', '11'), ',', '111'), ':', '1111')
)
, 0
)
FROM tbl
/
-- Finally, hakmem...Implemented in PL/SQL hakmem is quite fast. On 10gR2 it's even faster. :-) You can read more about hakmem here.
SELECT n
, MOD(
BITAND(
(n - BITAND(n / 2, 3681400539) - BITAND(n / 4, 1227133513))
+ (n - BITAND(n / 2, 3681400539) - BITAND(n / 4, 1227133513)) / 8
, 3340530119
)
, 63
) cnt
FROM tbl
WHERE n BETWEEN 0 AND 4294967295
/
Update 06/24/2005: Here you can find more about bitcount implementations in C.
Update 08/08/2005: Bit Twiddling Hacks
2 comments:
'bout replace algorithm - where is (c) sign? :-)
WBR, RA\/EN from sql.ru.
22.06.2005...
JFF
Oops :-)
Haven't read from beginning.
WBR, "NO-BUDDY" :(
Post a Comment