我说过值
0.36388617850285954
,当我使用Javascript .toString(36)
函数时,我得到输出"0.d3lh1pogpwk".
我想在golang中复制它,但是我没有真正的起点。
我将如何执行此操作?
Go base36 包无法正确转换它,因为 Javascript 的
toString(36)
不会对 float64 进行 Base36 编码,它使用基数 36 来表示它。关于此函数如何在 Number
对象上工作的细节,文档缺乏亮点(并且只有数字对象),并且逻辑也确实很奇怪,但位于此处:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toString#说明
基本上,在非整数的情况下,通过将小数点左侧的转换与点连接起来,然后将转换值转换为以N为基数的数字(其中N是传入的基数)小数点右边的。例如
baseNLeft + "." + baseNRight
上面的文档链接中还解释了有关底片的其他注意事项。具体来说,它们保留负数并简单地转换数字,然后替换负号,而不是使用二进制补码表示形式。
在我看来,此功能不适合除 Javascript 本身之外的任何其他语言,我建议谨慎跨语言使用它。
关于问题本身的答案,即如何在 Go 中做到这一点。遵循相同的愚蠢语义,并对数十万个测试用例进行单元测试,以检查 Javascript 和 Go 实现中的
f(x) = y
。逻辑的实际规范位于 ECMA 规范中:https://www.ecma-international.org/ecma-262/6.0/#sec-tostring-applied-to-the-number-type
注意:Go 中有一个名为
otto
(github.com/robertkrimen/otto) 实现的 Javascript 引擎,但它不能正确执行 Number.toString(radix)
功能。另外,如果这是它的唯一目的,那么它是一个需要导入的繁重的库。
在尝试从线程 ID 生成 Twitter/X 令牌时,我遇到了类似的问题。虽然最初的函数是用 JavaScript 编写的,并且我认为实现起来很简单,但结果比预期的要复杂。
需要注意的是,
.toString(X)
的 JavaScript 实现存在一些问题,但由于担心向后兼容性,这些问题不太可能得到修复。
我在 Go 中解决了这个问题,并获得了一致且准确的结果。我创建了一个公共要点,我已使用您的示例对其进行了更新:
https://gist.github.com/the-hotmann/a745c76c806128db68700685105a20e8#file-twittergettoken-go-L38-L43