英文:
uint(-5.0), where parameter is a float64, = 18446744073709551611?
问题
在Go之旅的第13步中,我稍微修改了脚本
package main
import (
"fmt"
"math"
)
func main() {
var x, y int = 3, 4
var f float64 = math.Sqrt(float64(x*x + y*y))
var z uint = uint(f)
fmt.Println(x, y, z, f)
}
这将返回:3 4 5 5,没问题。
但是当我做了这个改变:对f
取反:
func main() {
var x, y int = 3, 4
var f float64 = - math.Sqrt(float64(x*x + y*y))
var z uint = uint(f)
fmt.Println(x, y, z, f)
}
它的输出是:3 4 18446744073709551611 -5
为什么uint
方法将__-5.0__ 转换为 18446744073709551611?
难道没有什么东西 - 一个算法? - 在底层尝试检查它在做什么吗?
就像uint
方法是从具有尾数和指数的浮点数到整数的二进制级别的强制转换一样?
发生了什么?
如果我被误导了,并且uint
方法不是像我所认为的那样的转换函数,
而是像在_C_中可以找到的(uint)f
这样的强制转换方法,
那么有哪个转换函数可以确保:
uint z = anotherFunction(any float64)
将返回该浮点数的正整数值?
英文:
In the Tour of Go, step 13, I changed a bit the script
package main
import (
"fmt"
"math"
)
func main() {
var x, y int = 3, 4
var f float64 = math.Sqrt(float64(x*x + y*y))
var z uint = uint(f)
fmt.Println(x, y, z, f)
}
This returns: 3 4 5 5, fine.
But when I do this change: negating f
:
func main() {
var x, y int = 3, 4
var f float64 = - math.Sqrt(float64(x*x + y*y))
var z uint = uint(f)
fmt.Println(x, y, z, f)
}
It responds: 3 4 18446744073709551611 -5
Why does the -5.0 being converted to 18446744073709551611 by the uint
method?
Isn't there something - an algorithm? - trying to check what it is doing beneath?
It's like the uint
method was brutally casting at binary level from float with mantissa and exponent to an integer?
What is happening?
If I am misled, and that methods uint
aren't conversion functions like I believed,
but cast methods like you could find (uint)f
in C,
what is the conversion function that ensure that:
uint z = anotherFunction(any float64)
will return the positive integer value of that float number?
答案1
得分: 5
f
的值是一个负数:-5.0
。当你将其转换为无符号类型的值时,你会得到什么结果?无符号类型有一个有效的范围/表示,其中没有空间容纳-5
。
Go(像大多数其他语言一样)使用二进制补码来表示整数。当你将有符号整数转换为无符号整数时,表示(内存中的二进制数据)保持不变,但数字将被解释为不同的值。
通常情况下,当将负的有符号值转换为无符号值时,可以使用以下公式计算结果:
结果:MAX_VALUE + x + 1 = MAX_VALUE - ABS(x) + 1
例如,当将类型为int8
的-5
转换为uint8
时,结果将为:
255 - 5 + 1 = 251
将类型为int64
的-5
转换为uint64
也是同样的道理:
18446744073709551615 - 5 + 1 = 18446744073709551611
(注意:int
和uint
的大小取决于平台,Go Playground上的大小为64位,与int64
和uint64
相同。)
最后一个缺失的部分:你的f
是float64
类型。根据规范:转换:数值类型之间的转换,将float64
转换为整数时:
> 对于非常量数值的转换,应用以下规则:
>
> [...]
>
> 2. 将浮点数转换为整数时,小数部分被丢弃(朝零截断)。
因此,-5.0
被转换为-5
,然后可以使用上述算法来确定将其解释为uint
类型的值。
英文:
Value of f
is a negative number: -5.0
. What would you expect when you convert this to a value of an unsigned type? Unsigned types have a valid range / representation where there's no room for -5
.
Go (like most other languages) uses 2's complement to represent integers. When you convert a signed integer to an unsigned integer, the representation (binary data in memory) is kept, but the number will be interpreted differently.
In general, when converting a negative signed value to an unsigned value, you can calculate the result using:
result: MAX_VALUE + x + 1 = MAX_VALUE - ABS(x) + 1
So for example when converting -5
of type int8
to uint8
, the result will be:
255 - 5 + 1 = 251
The same goes for converting -5
of type int64
to uint64
:
18446744073709551615 - 5 + 1 = 18446744073709551611
(Note: size of int
and uint
is platform dependent, on the Go Playground it is of size 64-bit, same as int64
and uint64
.)
The last missing piece: your f
is of type float64
. Converting float64
to integer from Spec: Conversions: Conversions between numeric types:
> For the conversion of non-constant numeric values, the following rules apply:
>
> [...]
>
> 2. When converting a floating-point number to an integer, the fraction is discarded (truncation towards zero).
So -5.0
is converted to -5
, then the above algorithm can be used how this will look like when interpreted as a value of type uint
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论