Peter Larsson Blog

Patron Saint of Lost Yaks

Simple base converter

Here is a simple base converter that manages [from and to] base 2 to 16.

CREATE FUNCTION    dbo.fnBaseConvert
(
    @Value VARCHAR(8),
    @FromBase TINYINT,
    @ToBase TINYINT
)
RETURNS VARCHAR(32)
AS
BEGIN
    RETURN (
                SELECT     SUBSTRING('0123456789abcdef', 1 +(x.theValue % CAST(POWER(CAST(@ToBase AS FLOAT), v.Number + 1) AS BIGINT)) / CAST(POWER(CAST(@ToBase AS FLOAT), v.Number) AS BIGINT), 1)
                FROM        (
                                SELECT SUM((CHARINDEX(SUBSTRING(@Value, LEN(@Value) - Number, 1), '0123456789abcdef') - 1) * CAST(POWER(CAST(@FromBase AS FLOAT), Number) AS BIGINT)) AS theValue
                                FROM    master..spt_values
                                WHERE   Type = 'P'
                                        AND Number < LEN(@Value)
                                HAVING MIN(CHARINDEX(SUBSTRING(@Value, LEN(@Value) - Number, 1), '0123456789abcdef')) > 0
                                        AND MAX(CHARINDEX(SUBSTRING(@Value, LEN(@Value) - Number, 1), '0123456789abcdef')) <= @FromBase
                            ) AS x
                INNER JOIN  master..spt_values AS v ON v.Type = 'P'
                WHERE       x.theValue >= 0
                            AND v.Number < CEILING(0.00000005 + LOG(COALESCE(NULLIF(x.theValue, 0), 1)) / LOG(@ToBase))
                            AND @FromBase BETWEEN AND 16
                            AND @ToBase BETWEEN 2 AND 16
                ORDER BY    v.Number DESC
                FOR XML     PATH('')
            )
END