79622835

Date: 2025-05-15 07:43:54
Score: 3
Natty:
Report link

I went with tho old analogue approach. I find this easier to get my head around.

create or alter function [dbo].[getbitmap02](@gbm_in decimal(38,0) )

returns varchar(150)

as

begin

--

-- The maximum input number is 38 9s ( (10^38)-1 ), which gives a maximum 127 bit output string

--

declare @thenum decimal(38,0)

set @thenum = @gbm_in

declare @nxtpowof2 decimal(38,0)

declare @thestrng varchar(150)

declare @thestrng_50_0s varchar(50)

set @thestrng_50_0s = '00000000000000000000000000000000000000000000000000'

declare @thestrng_all_150_0s varchar(150)

set @thestrng_all_150_0s = concat( @thestrng_50_0s , @thestrng_50_0s , @thestrng_50_0s )

declare @bitcount_int smallint

--

-- First find the exponent of the target number, this will be of the form n.nnnnnnn

-- (unless the target number is an exact power of 2.) we are only interested

-- in the integer part of the exponent, as this is the highest power of 2 in the

-- target number.

set @bitcount_int = log( @thenum,2)

-- the first bit is always a 1, so might aswell initialise it that way

set @thestrng = '1'

-- Because sqlserver has difficulty differentiating between e.g.

-- 126 and 125.9999999999999999999999999, we have to adjust the value of

-- @nxtpowof2 to the highest power of 2 below the target value. we do this

-- by adjusting down the value of @bitcount_int.

-- if i try the power of 2 function with an exponent greater than 122 i get an error.

-- so i have to convert to decimal(38,0) and then multiply by the appropriate power

-- of 2.

-- 126 is the maximum power of 2 less than 9999999999999999999999999999999999999,

-- so this is the maximum power of 2 that we will have to cater for.

if @thenum <

case

when @bitcount_int <= 122 then power(2.0,@bitcount_int)

when @bitcount_int = 123 then cast( power(2.0,122) as decimal(38,0) ) *2

when @bitcount_int = 124 then cast( power(2.0,122) as decimal(38,0) ) *4

when @bitcount_int = 125 then cast( power(2.0,122) as decimal(38,0) ) *8

when @bitcount_int = 126 then cast( power(2.0,122) as decimal(38,0) ) *16

end

set @bitcount_int = @bitcount_int -1

-- as we have already set the 1st bit we have to reduce the target value

-- by the value of the first bit, whose exponent is held in @bitcount_int.

set @thenum = @thenum -

case

when @bitcount_int <= 122 then power(2.0,@bitcount_int)

when @bitcount_int = 123 then cast( power(2.0, 122) as decimal(38,0) ) *2

when @bitcount_int = 124 then cast( power(2.0, 122) as decimal(38,0) ) *4

when @bitcount_int = 125 then cast( power(2.0, 122) as decimal(38,0) ) *8

when @bitcount_int = 126 then cast( power(2.0, 122) as decimal(38,0) ) *16

end

-- once again, as we have already set the 1st bit we have to reduce the exponent of

-- @nxtpowof2 value by 1 i.e. we have to reduce the bitcount holder @bitcount_int by 1.

set @bitcount_int = @bitcount_int-1

-- sets up the next power of 2 to test for presence, and if so, subsequent subtraction.

set @nxtpowof2 =

case

when @bitcount_int <= 122 then power(2.0,@bitcount_int)

when @bitcount_int = 123 then cast( power(2.0, 122) as decimal(38,0) ) *2

when @bitcount_int = 124 then cast( power(2.0, 122) as decimal(38,0) ) *4

when @bitcount_int = 125 then cast( power(2.0, 122) as decimal(38,0) ) *8

when @bitcount_int = 126 then cast( power(2.0, 122) as decimal(38,0) ) *16

end

while @bitcount_int > -1

begin

-- if the target number becomes 0, all the remaining bits in the bitstring will be 0.

-- so set them and exit the loop.

if @thenum = 0

begin

-- if the target number becomes 0 we have to set the bitcount back up by 1 to get the correct

-- number of 0s

set @bitcount_int = @bitcount_int +1

set @thestrng = concat (@thestrng , substring (@thestrng_all_150_0s, 1, @bitcount_int ) )

break

end -- if @thenum = 0

-- if @thenum >= @nxtpowof2 ,then the next power of 2 is present so we add a 1 to the

-- bit string, and decrement the target number by that power of 2. otherwise the next

-- power of 2 is not present so we add a 0.

if @thenum>= @nxtpowof2

begin

set @thestrng = concat (@thestrng , '1' )

set @thenum = @thenum -

case

when @bitcount_int <= 122 then power(2.0,@bitcount_int)

when @bitcount_int = 123 then cast( power(2.0, 122) as decimal(38,0) ) *2

when @bitcount_int = 124 then cast( power(2.0, 122) as decimal(38,0) ) *4

when @bitcount_int = 125 then cast( power(2.0, 122) as decimal(38,0) ) *8

when @bitcount_int = 126 then cast( power(2.0, 122) as decimal(38,0) ) *16

end

end

else set @thestrng = concat (@thestrng , '0' )

-- sets up the next power of 2 to test for presence, and if so, subsequent subtraction.

set @bitcount_int = @bitcount_int -1

set @nxtpowof2 =

case

when @bitcount_int <= 122 then power(2.0,@bitcount_int)

when @bitcount_int = 123 then cast( power(2.0, 122) as decimal(38,0) ) *2

when @bitcount_int = 124 then cast( power(2.0, 122) as decimal(38,0) ) *4

when @bitcount_int = 125 then cast( power(2.0, 122) as decimal(38,0) ) *8

when @bitcount_int = 126 then cast( power(2.0, 122) as decimal(38,0) ) *16

end

end -- loop

return (@thestrng )

end

go

To verify results from above I run them through the function below.

create or alter function [dbo].[bitmap_getnum02](@bmgn_in varchar(200) )

returns decimal(38,0)

as

begin

declare @thenum decimal(38,0)

declare @thebit smallint

declare @thestrng varchar(200)

set @thestrng = @bmgn_in

declare @bitcount_int smallint

declare @count smallint

set @count = len (@thestrng)

set @bitcount_int = 1 -- @count

set @thenum = 0

-- get the first bit of the input string

set @thebit =

case when substring(@thestrng ,@bitcount_int,1) = '1' then 1

else 0

end

while @bitcount_int <= @count

begin

-- if the current bit is a 1, add the corresponding power of 2 to the total @thenum

if @thebit = 1

begin

if @count-@bitcount_int <= 122

set @thenum = @thenum + ( power( 2.0, (@count-@bitcount_int) ) )

else if @count-@bitcount_int = 123

set @thenum = @thenum + cast(power(2.0,122) as numeric(38,0) ) * 2

else if @count-@bitcount_int = 124

set @thenum = @thenum + cast(power(2.0,122) as numeric(38,0) ) * 4

else if @count-@bitcount_int = 125

set @thenum = @thenum + cast(power(2.0,122) as numeric(38,0) ) * 8

else if @count-@bitcount_int = 126

set @thenum = @thenum + cast(power(2.0,122) as numeric(38,0) ) * 16

end -- if @thebit = 1

-- move the bit pointer on by one

set @bitcount_int = @bitcount_int +1

-- if the remaining characters of the target bitstring contains all 0's (no 1's), exit the loop

if charindex ( '1', substring (@thestrng ,(@bitcount_int), (200-@bitcount_int) ) ) < 0.5

begin

break

end

-- get the next bit of the input string

set @thebit =

case when substring(@thestrng ,(@bitcount_int),1) = '1' then 1

else 0

end

end -- loop

-- any integer number n can be represented as a sequence of powers of 2 added together.

-- e.g. 23 = 1*2^4 +0*2^3 +1*2^2 +1*2^1 +1*2^0 or 10111 or approx 2 ^ 4.52356195605701287.

-- in the case of 23 ,the integer part of the exponent represents the highest bit in 10111,

-- and the decimal part represents the collection of bits that come after the first bit 0111.

return (@thenum)

end

go

Reasons:
  • RegEx Blacklisted phrase (1): i get an error
  • Long answer (-1):
  • No code block (0.5):
  • User mentioned (1): @thenum
  • User mentioned (0): @thenum
  • User mentioned (0): @gbm_in
  • User mentioned (0): @nxtpowof2
  • User mentioned (0): @thestrng
  • User mentioned (0): @thestrng_50_0s
  • User mentioned (0): @thestrng_50_0s
  • User mentioned (0): @thestrng_all_150_0s
  • User mentioned (0): @thestrng_all_150_0s
  • User mentioned (0): @thestrng_50_0s
  • User mentioned (0): @thestrng_50_0s
  • User mentioned (0): @thestrng_50_0s
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @thestrng
  • User mentioned (0): @nxtpowof2
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @thenum
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @thenum
  • User mentioned (0): @thenum
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @nxtpowof2
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @bitcount_int-1
  • User mentioned (0): @nxtpowof2
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @thenum
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @thestrng
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @thenum
  • User mentioned (0): @thenum
  • User mentioned (0): @nxtpowof2
  • User mentioned (0): @thenum
  • User mentioned (0): @nxtpowof2
  • User mentioned (0): @thestrng
  • User mentioned (0): @thenum
  • User mentioned (0): @thenum
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @thestrng
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @nxtpowof2
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @thenum
  • User mentioned (0): @thebit
  • User mentioned (0): @thestrng
  • User mentioned (0): @thestrng
  • User mentioned (0): @bmgn_in
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @count
  • User mentioned (0): @count
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @count
  • User mentioned (0): @thenum
  • User mentioned (0): @thebit
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @count
  • User mentioned (0): @thenum
  • User mentioned (0): @thebit
  • User mentioned (0): @thenum
  • User mentioned (0): @thenum
  • User mentioned (0): @thenum
  • User mentioned (0): @thenum
  • User mentioned (0): @thenum
  • User mentioned (0): @thenum
  • User mentioned (0): @thenum
  • User mentioned (0): @thenum
  • User mentioned (0): @thenum
  • User mentioned (0): @thenum
  • User mentioned (0): @thebit
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @bitcount_int
  • User mentioned (0): @thebit
  • Filler text (0.5): 00000000000000000000000000000000000000000000000000
  • Filler text (0): 9999999999999999999999999
  • Filler text (0): 9999999999999999999999999999999999999
  • Low reputation (1):
Posted by: Joe Boyle