将int64转换为uint64时,是否保留符号? [英] When casting an int64 to uint64, is the sign retained?

查看:385
本文介绍了将int64转换为uint64时,是否保留符号?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含负数的int64变量,我希望从包含一个正数的uint64变量中减去它:

I have an int64 variable which contains a negative number and I wish to subtract it from an uint64 variable which contains a positive number:

var endTime uint64
now := time.Now().Unix()
endTime = uint64(now)
var interval int64
interval = -3600
endTime = endTime + uint64(interval)

上面的代码似乎可以工作,但是我想知道我是否可以依靠它.对于Go语言的新手,我感到很惊讶,在将负数强制转换为uint64后仍保持负数–我计划减去(现在强制转换后)正值以获得所需的值.

The above code appears to work but I wonder if I can rely on this. I am surprised, being new to Go, that after casting a negative number to uint64 that it remains negative -- I had planned to subtract the now positive value (after casting) to get what I wanted.

推荐答案

将带符号的数字转换为无符号的数字不会保持负数,而是不能,因为有效的无符号类型范围不包括负数.如果打印uint(interval),则肯定会看到一个正数.

Converting a signed number to an unsigned number will not remain negative, it can't, as the valid range of unsigned types doesn't include negative numbers. If you print uint(interval), you will certainly see a positive number printed.

您所经历的是确定性的,您可以依靠它(但这并不意味着您应该这样做).这是Go(和大多数其他编程语言)使用 2的完成度存储有符号整数类型的结果. /a>表示形式.

What you experience is deterministic and you can rely on it (but it doesn't mean you should). It is the result of Go (and most other programming languages) storing signed integer types using the 2's completement representation.

这意味着在负数的情况下,使用n位将值-x(其中x为正)存储为正值2^n - x的二进制表示.这样做的好处是,可以按位加数字,无论结果是负还是正,结果都是正确的.

What this means is that in case of negative numbers, using n bit, the value -x (where x is positive) is stored as the binary representation of the positive value 2^n - x. This has the advantage that numbers can be added bitwise, and the result will be correct regardless of whether they are negative or positive.

因此,当您拥有带负号的负数时,它基本上会存储在内存中,就像您要从0中减去其绝对值一样.这意味着,如果将负的有符号值转换为无符号值,然后将其添加到无符号值,则结果将是正确的,因为会以一种有用的方式发生溢出.

So when you have a signed negative number, it is basically stored in memory like if you would subtract its absolute value from 0. Which means that if you convert a negative, signed value to unsigned, and you add that to an unsigned value, the result will be correct because overflow will happen, in a useful way.

将类型int64的值转换为uint64不会更改内存布局,仅更改类型.因此,int64有8个字节,转换后的uint64将具有相同的8个字节.并且如上所述,存储在这8个字节中的表示是与值0 - abs(x)的位模式相同的位模式.因此,在无符号世界中,如果将abs(x)0中减去,则转换结果将是一个数字.是的,这不会是负数(因为类型是无符号的),而是一个大"数字,从uint64类型的最大值开始递减.但是,如果将一个大于abs(x)y数字添加到此大"数字,则会发生溢出,并且结果将类似于y - abs(x).

Converting a value of type int64 to uint64 does not change the memory layout, only the type. So what 8 bytes the int64 had, the converted uint64 will have those same 8 bytes. And as mentioned above, the representation stored in those 8 bytes is the bit pattern identical to the bit pattern of value 0 - abs(x). So the result of the conversion will be a number that you would get if you would subtract abs(x) from 0, in the unsigned world. Yes, this won't be negative (as the type is unsigned), instead it will be a "big" number, counting down from the max value of the uint64 type. But if you add an y number bigger than abs(x) to this "big" number, overflow will happen, and the result will be like y - abs(x).

请参见以下简单示例演示正在发生的事情(在游乐场上尝试一下):

See this simple example demonstrating what's happening (try it on the Go Playground):

a := uint8(100)
b := int8(-10)
fmt.Println(uint8(b)) // Prints 226 which is: 0 - 10 = 256 - 10
a = a + uint8(b)
fmt.Println(a)        // Prints 90 which is: 100 + 226 = 326 = 90
                      //           after overflow: 326 - 256 = 90

如上所述,您不应依赖于此,因为这可能会引起混乱.如果您打算使用负数,请使用带符号的类型.

As mentioned above, you should not rely on this, as this may cause confusion. If you intend to work with negative numbers, then use signed types.

如果您使用已经使用uint64值的代码库,则可以使用uint64值进行减法运算而不是加法运算:

And if you work with a code base that already uses uint64 values, then do a subtraction instead of addition, using uint64 values:

interval := uint64(3600)
endTime -= interval

还请注意,如果您具有 time.Time 值,则应利用其 Time.Add() 方法:

Also note that if you have time.Time values, you should take advantage of its Time.Add() method:

func (t Time) Add(d Duration) Time

您可以指定 time.Duration 添加到时间中,该时间可以是否定,如果您想回到过去,就像这样:

You may specify a time.Duration to add to the time, which may be negative if you want to go back in time, like this:

t := time.Now()
t = t.Add(-3600 * time.Second)

time.Duration更具表现力:我们看到上面指定的值明确使用秒.

time.Duration is more expressive: we see the value we specified above uses seconds explicitly.

这篇关于将int64转换为uint64时,是否保留符号?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆