An SQL function for radix conversion algorithm

不想你离开。 提交于 2020-01-06 12:41:08

问题


Do we have anything predefined function in sql server to work with radix conversion? The scenario is function takes a number as an input parameter and returns the binary radix conversion for the given number.

For example, if the input is 12, it has to return "2^3+2^2":

"5=2^2+2^0"

...And so until 15. The maximum input is 15.

So maximum values we need to search for is:

 2^0,2^1,2^2,2^3.

We can store these 2 to the power values(2^0,2^1,2^2,2^3) in variables and return those variables. For example, if we stored it like this:

x=2^0
y=2^1
z=2^2
p=2^3

When our input value is 12, it has to return p+z. When our input value is 8 it has to return p. When our input value is 15 it has to return x+y+z+p.

And so on...


回答1:


No build in function as far as I'm aware... what you basically want is to convert the input to a binary string, and then iterate through the characters

ie:

  • 15 -> 1111 = 2^3 + 2^2 + 2+1 + 2^0
  • 12 -> 0110 = 2^2 + 2^1

unfortunately theres not a build in convert to binary string function that I can find. There is an ability to convert to a hex string though, if you are on SQL Server 2008 or later.

DECLARE @i INT = 15
DECLARE @b VARBINARY(1) = CONVERT(VARBINARY(1),@i)
DECLARE @s NVARCHAR(2) = CONVERT(NVARCHAR(2), @b,2)

SELECT @i AS i, @b AS [binary], @s AS [hexString]

-- returns 
-- i    | binary    | hexString
-- ------------------------------
-- 15   | 0x0F      | 0F 

As you only care about 0 - 15 I'd be tempted to just go with a user-defined function that takes a case statement. Eg:

CREATE FUNCTION fn_GetRadix(@i INT)
RETURNS NVARCHAR(255)
AS
BEGIN
    DECLARE @Output NVARCHAR(255)
    SELECT @Output = 
        CASE RIGHT(CONVERT(VARCHAR(2), CONVERT(VARBINARY(1), @i),2),1)
        WHEN '0' THEN ''
        WHEN '1' THEN '2^0'
        -- etc etc
        WHEN 'F' THEN '2^3 + 2^2 + 2^1 + 2^0'
        ELSE 'something else' END

    RETURN @Output

END

Not exactly ideal, but might be good enough. It would be possible to get a function that works generically for higher input values. You'd need to start by converting to a binary string (see SQL Server Convert integer to binary string), and then iterate the characters to build up the output.

EDIT 1:

Here is a function to convert an arbitary integer to a binary string:

CREATE FUNCTION fnGetBinaryString(@i INT)
RETURNS NVARCHAR(MAX)
AS
BEGIN
    DECLARE @hexString NVARCHAR(MAX) 
    SELECT @hexString = CONVERT(VARCHAR(MAX), CONVERT(VARBINARY(MAX), @i) ,2)

    DECLARE @binString NVARCHAR(MAX) = ''
    DECLARE @counter INT = LEN(@hexString)
    DECLARE @char CHAR(1)
    WHILE (@counter > 0)
    BEGIN
        SELECT @char = SUBSTRING(@hexString, @counter, 1)
        SELECT @binString = 
        CASE @char 
            WHEN '0' THEN '0000' WHEN '1' THEN '0001'
            WHEN '2' THEN '0010' WHEN '3' THEN '0011'
            WHEN '4' THEN '0100' WHEN '5' THEN '0101'
            WHEN '6' THEN '0110' WHEN '7' THEN '0111'
            WHEN '8' THEN '1000' WHEN '9' THEN '1001'
            WHEN 'A' THEN '1010' WHEN 'B' THEN '1011'
            WHEN 'C' THEN '1100' WHEN 'D' THEN '1101'
            WHEN 'E' THEN '1110' WHEN 'F' THEN '1111' END
            + @binString
        SELECT @counter = @counter - 1
    END
    RETURN  @binString
END

Now building on that we simply iterate though the characters in the binary string from right to left, every time we hit a one we add a result 2 ^ (index from right)

EDIT 2

And here is the function above modified to give you your desired output string:

CREATE FUNCTION fnGetRadixString(@i INT)
RETURNS NVARCHAR(MAX)
AS
BEGIN
    DECLARE @hexString NVARCHAR(MAX) 
    SELECT @hexString = CONVERT(VARCHAR(MAX), CONVERT(VARBINARY(MAX), @i) ,2)

    DECLARE @binString NVARCHAR(MAX) = ''
    DECLARE @counter INT = LEN(@hexString)
    DECLARE @char CHAR(1)
    WHILE (@counter > 0)
    BEGIN
        SELECT @char = SUBSTRING(@hexString, @counter, 1)
        SELECT @binString = 
        CASE @char 
            WHEN '0' THEN '0000' WHEN '1' THEN '0001'
            WHEN '2' THEN '0010' WHEN '3' THEN '0011'
            WHEN '4' THEN '0100' WHEN '5' THEN '0101'
            WHEN '6' THEN '0110' WHEN '7' THEN '0111'
            WHEN '8' THEN '1000' WHEN '9' THEN '1001'
            WHEN 'A' THEN '1010' WHEN 'B' THEN '1011'
            WHEN 'C' THEN '1100' WHEN 'D' THEN '1101'
            WHEN 'E' THEN '1110' WHEN 'F' THEN '1111' END
            + @binString
        SELECT @counter = @counter - 1
    END

    -- now we have a binary string representation of the number
    -- iterate it from right to left

    DECLARE @rString NVARCHAR(MAX) = ''
    SET @counter = LEN(@binString)
    DECLARE @Power INT = 0
    WHILE (@counter > 0)
    BEGIN
        IF SUBSTRING(@binString, @counter, 1) = '1'
            SELECT @rString = '2^' + CAST(@Power AS NVARCHAR(128)) + '+'

        SELECT @Power = @Power + 1
        SELECT @counter = @counter - 1
    END
    -- trim last +
    IF LEN(@rString) > 0 SELECT @rString = LEFT(@rString, LEN(@rString) - 1)

    RETURN  @rString
END


来源:https://stackoverflow.com/questions/21428317/an-sql-function-for-radix-conversion-algorithm

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!