2014-01-29 2 views
0

Есть ли у нас какая-либо предопределенная функция в sql-сервере для работы с преобразованием radix? Сценарий - функция принимает число как входной параметр и возвращает двоичное преобразование радикса для данного номера.Функция SQL для алгоритма преобразования radix

Например, если на вход 12, он должен вернуться "2^3 + 2^2":

"5=2^2+2^0" 

... И так до 15. Максимальный входной сигнал не равен 15.

Поэтому максимальные значения мы должны искать это:

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, он должен вернуть р + г. Когда наше входное значение равно 8, оно должно вернуть p. Когда наше входное значение равно 15, оно должно возвращать x + y + z + p.

И так далее ...

ответ

0

Нет сборки в зависимости, насколько я знаю ... что вы в принципе хотите, чтобы преобразовать входной сигнал в двоичную строку, а затем перебирать символы

т.е.:

  • 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 я был бы соблазн просто пойти с определенной пользователем функции, которая принимает дела заявление. Например:

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), а затем итерации символов для создания вывода.

EDIT 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^(индекс справа)

EDIT 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 
+0

Благодарность за IDEA..apart от преобразования в двоичную у меня есть другое approach.finding ближайший от 2 до значения мощности для заданное число. Например, для 12 ближайший 2 к значению мощности будет 2^3 = 8. Теперь 12-8 = 4. Теперь найдите ближайшее 2 к значению мощности для этого 4, которое равно 2^2. Это выглядит хорошо для меня, но я не могу написать рекурсивную функцию для этой идеи. Могу помочь мне – Santosh

+0

@Santosh - см. дальнейшие изменения, которые я сделал, которые показывают, что эта идея реализована –

Смежные вопросы