用于基数转换算法的SQL函数 [英] An SQL function for radix conversion algorithm

查看:149
本文介绍了用于基数转换算法的SQL函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们在sql server中有什么预定义的函数来处理基数转换吗?
场景是函数将数字作为输入参数,并返回给定数字的二进制基数转换。例如,如果输入为12,它必须返回2 ^ 3 + 2 ^ 2:

 5 = 2 ^ 2 + 2 ^ 0

...等到15为止。最大输入值为15。



因此我们需要搜索的最大值是:

pre $ code> 2 ^ 0,2 ^ 1,2 ^ 2,2 ^ 3。

我们可以将这2个值存储到功率值(2 ^ 0,2 ^ 1,2 ^ 2 ,2 ^ 3)在变量中并返回这些变量。例如,如果我们像这样存储它:

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

当我们的输入值是12时,它必须返回p + z。
当我们的输入值是8时,它必须返回p。
当输入值为15时,它必须返回x + y + z + p。我知道基本上想要的是将输入转换为二进制字符串,然后遍历字符

即:


    <15> 15 - > 1111 = 2 ^ 3 + 2 ^ 2 + 2 + 1 + 2 ^ 0
    li 12→0110 = 2 ^ 2 + 2 ^ 1


不幸的是,这不是一个内置的转换为二进制字符串函数,我可以找到。
如果您使用的是SQL Server 2008或更高版本,则可以转换为十六进制字符串。

  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]

- 返回
- i |二进制| hexString
- ------------------------------
- 15 | 0x0F | 0F

由于您只关心0到15,这个函数定义了一个case语句。例如:
$ b $

  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)
'0'THEN''
'1'THEN'2 ^ 0'
- 等等
当'F'THEN'2 ^ 3 + 2 ^ 2 + 2 ^ 1 + 2 ^ 0'
ELSE'别的东西'END

RETURN @Output

END

不完全理想,但可能够好。
有可能得到一个通用的函数来获得更高的输入值。
您需要先转换为二进制字符串(请参阅 SQL Server将整数转换为二进制字符串),然后遍历字符以构建输出。 编辑1:



这是一个将任意整数转换为二进制字符串的函数:

  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
当'0'则'0000'时' 1'然后'0001'
当'2'然后'0010'当'3'然后'0011'
当'4'然后'0100'当'5'然后'0101'
''''然后'0110'当'7'然后'0111'
当'8'然后'1000'当'9'然后'1001'
当'A'时'1010''当' B'THEN'1011'
'C'然后'1100'当'D'然后'1101'
当'E'然后'1110'当'F'然后'1111'结束
+ @binString
SELECT @counter = @counter - 1
END
RETURN @binString
END

现在建立在这个基础上,我们简单地遍历二进制字符串中的字符从右到左,每当我们碰到一个字符时,我们就添加一个结果2 ^(右边的索引) p>

编辑2



以上是修改后的功能, tput字符串:

$ $ p $ code 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
当'0'THEN' 0000''''''然后'0001'
当'2'然后'0010'当'3'然后'0011'
当'4'然后'0100'当'5'然后'0101'
当'6'然后'0110'当'7'然后'0111'
当'8'然后'1000'当'9'然后'1001'
当'A'然后' 1010''''''然后'1011'
当'C'然后'1100'当'D'然后'1101'
当'E'然后'1110'当'F'然后'1111' END
+ @binString
SELECT @counter = @counter - 1
END

- 现在我们有一个二进制字符串表示形式的数字
- - 从右到左迭代它

DECLARE @rString NVARCHAR(MAX)='
SET @counter = LEN(@binString)
DECLARE @Power INT = 0
WHILE(@counter> 0)
BEGIN
如果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


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...

解决方案

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

这篇关于用于基数转换算法的SQL函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆