uint(-5.0),其中参数为float64,= 18446744073709551611?

huangapple go评论72阅读模式
英文:

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?

uint(-5.0),其中参数为float64,= 18446744073709551611?

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

(注意:intuint的大小取决于平台,Go Playground上的大小为64位,与int64uint64相同。)

最后一个缺失的部分:你的ffloat64类型。根据规范:转换:数值类型之间的转换,将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.

huangapple
  • 本文由 发表于 2023年5月26日 17:05:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/76339294.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定