【问题标题】:Convert uint64 to int64 without loss of information在不丢失信息的情况下将 uint64 转换为 int64
【发布时间】:2015-01-10 16:55:57
【问题描述】:

以下代码的问题:

var x uint64 = 18446744073709551615
var y int64 = int64(x)

y-1。在不丢失信息的情况下,这两种数字类型之间转换的唯一方法是使用编码器和解码器吗?

buff bytes.Buffer
Encoder(buff).encode(x)
Decoder(buff).decode(y)

请注意,在您的典型情况下,我不会尝试直接进行数字转换。我更关心维护随机数生成器的统计特性。

【问题讨论】:

  • y 是-1?你的操作系统是 32 位的还是 64 位的?
  • 对投反对票的人来说,为什么投反对票? @VonC 64 位。
  • 我没有投反对票(这里是赞成票)。我问操作系统是因为tip.golang.org/doc/go1.1#int,您只能在 32 位操作系统中看到 -1。
  • @VonC 我会的。我敢打赌,我们已经将此 Varnish 设置为 32 位运行!
  • 如果y 不是 -1,你希望它是什么?您想在转换后断言 x == y 并且如果不是则有错误/恐慌?

标签: random go int64 uint64


【解决方案1】:

看到 -1 将与以 32 位运行的进程一致。

例如参见Go1.1 release notes(其中介绍了uint64

x := ^uint32(0) // x is 0xffffffff
i := int(x)     // i is -1 on 32-bit systems, 0xffffffff on 64-bit
fmt.Println(i)

使用fmt.Printf("%b\n", y) 可以帮助了解正在发生的事情(请参阅ANisus'answer

事实证明,OP wheaties 确认 (in the comments) 它最初以 32 位运行(因此是这个答案),但随后意识到 184467440737095516150xffffffffffffffff (-1) 反正:见 @987654326 @answer;

【讨论】:

  • 在 64 位机器上在 Varnish 之外运行我仍然可以看到它。它不会导致溢出恐慌,但它会返回-1,这几乎破坏了位的所有随机性。
  • @wheaties 好的,我在阅读 stackoverflow.com/a/16458451/6309 后提到了这种可能性
  • 我有点不知道你们两个中的哪一个给出了答案。您实际上向我指出了这样一个事实,即我在 32 位设置中运行 Varnish,这表明它总是会出现 -1 而 ANisus 说的很明显,我只是根据 32 位系统的经验得出了错误的结论.
  • @wheaties 我用操场上的例子完成了 ANisus 的答案。
  • 问题变了吗?我看不出这个答案与这个问题有什么关系。
【解决方案2】:

您的转化不会丢失转化中的任何信息。所有位都将保持不变。就是这样:

uint64(18446744073709551615) = 0xFFFFFFFFFFFFFFFF
int64(-1)                    = 0xFFFFFFFFFFFFFFFF

试试:

var x uint64 = 18446744073709551615 - 3

你将拥有y = -4


例如:playground

var x uint64 = 18446744073709551615 - 3
var y int64 = int64(x)
fmt.Printf("%b\n", x)
fmt.Printf("%b or %d\n", y, y)

输出:

1111111111111111111111111111111111111111111111111111111111111100
-100 or -4

【讨论】:

  • 我有点不知道你们两个中的哪一个给出答案。您正确地指出我错误地将 -1 解释为不是。然而,这种错误解释是在 32 位设置下运行 Varnish 的直接结果。我想我需要把它交给 VonC,但希望我能给你更多 +1。
  • 18446744073709551615 是 0xffffffffffffffff
  • @Anonymous:感谢您的关注。添加了缺失的 F
【解决方案3】:

uint64 和 int64 类型都可以表示 2^64 个离散整数值。

两者的区别在于 uint64 只保存正整数(0 到 2^64-1),而 int64 保存负整数和正整数,使用 1 位来保存符号(-2^63 到 2^63 -1)。

正如其他人所说,如果您的生成器正在生成 0xffffffffffffffff,uint64 会将其表示为原始整数 (18,446,744,073,709,551,615),而 int64 将解释 two's complement 值并返回 -1。

【讨论】:

    猜你喜欢
    • 2012-04-14
    • 1970-01-01
    • 1970-01-01
    • 2010-12-13
    • 1970-01-01
    • 2020-01-11
    相关资源
    最近更新 更多