问题
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