golang 简单实现的36进制

勤劳一沙鸥 · · 4058 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

概述

36进制:使用 [0-9,a-z] 描述,逢36进一,即称之为36进制

var num2char = "0123456789abcdefghijklmnopqrstuvwxyz"

典型应用:汽车号码牌,比如: 京 B0540Z;顺序生成序号等

进制转换规则参考16进制与10进制转换,大体如下:

  1. 10进制转36进制,用10进制数除了36,取余数得最低1位,然后把商继续除36,得第二位,直到商为0。举例:
  • 126110
  • 1261 除 36 余数 35 (对应 Z),商 1
  • 1 除 36 余数 1 (对应1),商 0 结束
  • 得到 (Z1)36
  1. 36进制转10进制,36进制数按权展开,从右边第一个数开始,每一个乘以16的n次方,n从0开始,每次递增1,然后得出来的每个数相加即是十进制数。举例:
  • (Z1)36 = 35 * 361+ 1 * 360 = 126110
  • (ABC)36 = 10 * 362 + 11 * 361+ 12 * 360 = 1336810

golang 程序实现:

编码:

// 10进制数转换   n 表示进制, 16 or 36
func NumToBHex(num, n int) string {
    num_str := ""
    for num != 0 {
        yu := num % n
        num_str = string(num2char[yu]) + num_str
        num = num / n
    }
    return strings.ToUpper(num_str)
}

解码

// 36进制数转换   n 表示进制, 16 or 36
func BHex2Num(str string, n int) int {
    str = strings.ToLower(str)
    v := 0.0
    length := len(str)
    for i := 0; i < length; i++ {
        s := string(str[i])
        index := strings.Index(num2char, s)
        v += float64(index) * math.Pow(float64(n), float64(length-1-i)) // 倒序
    }
    return int(v)
}

测试

func TestBHex2Num(t *testing.T) {
    assert.Equal(t, BHex2Num("1E6K", 36), 65036)
    assert.Equal(t, BHex2Num("FE0C", 16), 65036)

    assert.Equal(t, NumToBHex(65036, 36), "1E6K")
    assert.Equal(t, NumToBHex(65036, 16), "FE0C")
}

应用: 生成序号

日期+[A-Z][0-Z]顺序生产,例如 20190520-A0 20190520-A1 ... 20190520-ZZ

// 按 yymmdd-[A-z][0-Z] 形式生成序号
func UssNoGenerate(last string) string {
    prefix := time.Now().Format(DateTimeDate)
    value := 0
    if last != "" {
        suffix := strings.Split(last, "-")[1]
        value = BHex2Num(suffix, 36) + 1
    } else {
        value = BHex2Num("A0", 36)
    }
    return prefix + "-" + NumToBHex(value, 36)
}

应用测试:

func TestUssNoGenerate(t *testing.T) {
    last := UssNoGenerate("")
    for i := 0; i < 40; i++ {
        fmt.Println(last)
        last = UssNoGenerate(last)
    }

}

// 输出
20190520-A0
20190520-A1
20190520-A2
20190520-A3
...
20190520-AZ
20190520-B0
20190520-B1
20190520-B2
20190520-B3

最开始的需求即是生成这些编号,使用字符串截取运算等方式,可以完成,但代码不忍直视,所以改进为些版本。至少原理上非常容易理解。

你看出bug来了吗,欢迎留言


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:勤劳一沙鸥

查看原文:golang 简单实现的36进制

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

4058 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传