据我所知,没有内置函数...您基本上想要的是将输入转换为二进制字符串,然后遍历字符
即:
- 15 -> 1111 = 2^3 + 2^2 + 2+1 + 2^0
- 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]
-- returns
-- i | binary | hexString
-- ------------------------------
-- 15 | 0x0F | 0F
由于您只关心 0 - 15,我很想只使用带有 case 语句的用户定义函数。例如:
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
不完全理想,但可能足够好。
有可能获得一个通常适用于更高输入值的函数。
您需要首先转换为二进制字符串(请参阅SQL Server Convert integer to binary string),然后迭代字符以构建输出。
编辑 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
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
现在在此基础上,我们简单地从右到左迭代二进制字符串中的字符,每次我们点击一个,我们添加一个结果 2 ^(从右开始的索引)
编辑 2
这是上面修改后的函数,可以为您提供所需的输出字符串:
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