1

我正在制作 URL 缩短器,并且正在努力将数字(id)编码为字符串的最佳方式。

我使用的是字符 0-9、AZ、az,所以它基本上是 base-62 编码。这是非常基本的,但它并没有使用所有可能的代码。它将产生的代码是:

0, 1, ... y, z, 10, 11, ... zy, zz, 100, 101, ...

请注意,没有使用代码 00 到 0z,对于 000 到 0zz 也是如此,依此类推。我想使用所有代码,如下所示:

0, 1, ... y, z, 00, 01, ... zy, zz, 000, 001, ...

它将是 base-62 和 base-63 的某种组合,根据位置不同具有不同的基数......使用 base-62 很容易,例如:

create procedure tiny_GetCode
    @UrlId int
as
set nocount on

declare @Code varchar(10)
set @Code = ''

while (@UrlId > 0 or len(@Code) = 0) begin
    set @Code = substring('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', @UrlId % 62 + 1, 1) + @Code
    set @UrlId = @UrlId / 62
end

select @Code

但我还没有设法从中进行多基转换,以利用所有代码。

4

1 回答 1

4

我设法进行了转换。棘手的是,它不仅仅是混合基数转换,第一个字符的高基数也会影响较长代码的值。

我从一个更简单的案例开始;base-10 代码。我看到两位数范围有 10 个额外代码,三位数字范围有 100 个额外代码,依此类推:

0 - 9        : '0' - '9'
10 - 109     : '00' - '99'
110 - 1109   : '000' - '999'
1110 - 11109 : '0000' - '9999'

因此,代码中第一个字符的值不仅仅是基数提升到该位置,它还有一个偏移量。

将其应用于 base-62 编码后,这就是我最终得到的结果:

create function tiny_Encode(@UrlId int) returns varchar(10)
as
begin

  declare
    @Chars varchar(62),
    @Code varchar(10),
    @Value int,
    @Adder int

  set @Chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
  if (@UrlId < 63) begin
    set @Code = substring(@Chars, @UrlId, 1)
  end else begin
    set @UrlId = @UrlId - 1
    set @Value = 62
    set @Adder = 0
    while (@UrlId >= @Value * 63 + @Adder) begin
      set @Adder = @Adder + @Value
      set @Value = @Value * 62
    end
    set @Code = substring(@Chars, (@UrlId - @Adder) / @Value, 1)
    set @UrlId = ((@UrlId - @Adder) % @Value)
    while (@Value > 1) begin
      set @Value = @Value / 62
      set @Code = @Code + substring(@Chars, @UrlId / @Value + 1, 1)
      set @UrlId = @UrlId % @Value
    end
  end
  return @Code

end
于 2010-04-30T11:58:02.953 回答