【问题标题】:Why can't you store the minimum value of int64 into a uint64?为什么不能将 int64 的最小值存储到 uint64 中?
【发布时间】:2021-10-24 21:27:36
【问题描述】:

理论上 int64 适合 uint64,当然它们的数值会有所不同,因为第一个位是为 int64 上的符号保留的,但是为什么我不能进行这种转换呢?这对我来说似乎有效

import (
    "fmt"
    "math"
)

func main() {
    var randomNum uint64 = math.MinInt64
    fmt.Println(randomNum)
}

产生错误

constant -9223372036854775808 overflows uint64

这里的math.MinInt64-9223372036854775808,技术上是一个适合63 位加号的数字。

我主要研究这个,因为我想将 8 bytes 转换回具有正确符号的 int64,但到目前为止我只看到返回 uint64 的函数

binary.LittleEndian.Uint64(bytesArrays[0:8])

【问题讨论】:

  • "4 个字节回到 int64" --> 嗯,我希望 8 个字节。
  • @Keldorn 你的-3 有什么关系?你甚至运行了提供的代码吗?有明显的溢出错误

标签: go


【解决方案1】:

这种“转换”不起作用的原因是因为您的程序中没有转换。赋值不会隐式执行转换(接口类型除外)。

请参阅管理常量值分配的assignability rules

如果满足以下条件之一,则值 x 可分配给 T 类型的变量(“x 可分配给 T”):

  • x 的类型与 T 相同。
  • ...
  • x 是一个无类型的常量,可以用 T 类型的值表示。

在这种情况下,math.MinInt64 是一个无类型常量,但它不能用 uint64 类型的值表示,因为它是 defined

uint64 所有无符号 64 位整数的集合(0 到 18446744073709551615)

负 64 位整数和无符号 64 位整数之间的转换是可能的,但您需要一个真正的 conversion。然而,由于熟悉的规则,您仍然不能直接转换常量值:

如果 x 可以用 T 的值表示,则常数值 x 可以转换为类型 T。

所以,正确的做法是先将数字赋给一个非常量值:

x := int64(math.MinInt64)
y := uint64(x)
fmt.Println(y)

Playground link

【讨论】:

  • 我从来没有认为问题是由常量引起的,假设它是输入的,我盲目地测试该常量,你在 int64 和 uint64 之间转换的方式完全有意义,感谢建设性的回答
【解决方案2】:

int64 适合 uint64,但这不是问题中的代码所做的。代码将常量 math.MinInt64 分配给 uint64 变量 randomNum。编译器报错,因为常量不是 uint64 的representable

先赋值给一个变量,这样常量的规则就不适用了:

x := int64(math.MinInt64)
var randomNum = uint64(x)
fmt.Println(randomNum)

【讨论】:

    【解决方案3】:

    谁说你不能?好吧,编译器是这么说的。但是编译器的意思是你不能把value-9223372036854775808放到一个uint64变量中,这是真的;您需要将 位模式作为 int64 表示 -9223372036854775808,但表示它将被视为 uint64 的值uint64

    var randomNum uint64 = math.MinInt64 + math.MaxUint64 + 1
    

    哪个works fine——当然也可以做什么GastroHealth showed

    我主要研究这个,因为我想将 [8] 字节转换回具有正确符号的 int64,但到目前为止我只看到返回 uint64 的函数(例如 binary.LittleEndian.Uint64)。

    我们做的是显而易见的:

    signed := int64(v ^ 0x8000000000000000 - 0x8000000000000000)
    

    (嗯,看过几次就很明显了。)

    a complete example here(我使用大端,我更喜欢人类使用)。请注意,您可以在这里执行signed := int64(v);翻转和减法技巧非常适合用作您还没有变量的表达式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-13
      • 1970-01-01
      • 2020-10-27
      • 1970-01-01
      • 1970-01-01
      • 2020-02-24
      • 2015-01-10
      • 2020-11-05
      相关资源
      最近更新 更多