如何以正确的方式将 float64 数字更改为 uint64? [英] How to change a float64 number to uint64 in a right way?

查看:52
本文介绍了如何以正确的方式将 float64 数字更改为 uint64?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

包主功能主(){var n float64 = 6161047830682206209打印(uint64(n))}

输出将是:

6161047830682206208

看起来当float64变成uint64时,分数被丢弃了.

解决方案

这里的问题是常量和浮点数的表示.

常量以任意精度表示.浮点数使用 IEEE 754 标准表示.

规范:常量:

<块引用>

数字常量代表任意精度的值,不会溢出.

规范:数字类型:

<块引用>

float64 所有 IEEE-754 64 位浮点数的集合

在 IEEE 754 中,使用 64 位的双精度(Go 中的 float64)53 位 用于存储数字.这意味着可以表示的最大位数(max number)是2<<52的位数,即(1位表示符号):

2<<52 : 9007199254740992您的常数:6161047830682206209

精确到 15.95 位(16 位,但不是所有可以用 16 位描述的值,最多只能是 9007199254740992).

您尝试放入 float64 类型变量的整数常量只是 不适合 52 位,因此必须四舍五入,数字(或位)将被切断(丢失).

您可以通过打印原始的 n float64 数字来验证这一点:

var n float64 = 6161047830682206209fmt.Printf("%f
", n)fmt.Printf("%d
", uint64(n))

输出:

6161047830682206208.0000006161047830682206208

问题不在于转换,问题在于您尝试转换的 float64 值已经不等于您尝试分配给它的常量.

仅供好奇:

尝试使用更大的数字:与第一个常量相比 +500:

n = 6161047830682206709//与第一个相比 +500!fmt.Printf("%f
", n2)fmt.Printf("%d
", uint64(n2))

输出仍然相同(最后的数字/位被截断,包括+500!):

6161047830682206208.0000006161047830682206208

尝试一个较小的数字,其数字可以使用 52 位(小于 ~16 位)精确表示:

n = 7830682206209fmt.Printf("%f
", n)fmt.Printf("%d
", uint64(n))

输出:

7830682206209.0000007830682206209

Go Playground 上试试.

package main

func main() {
    var n float64 = 6161047830682206209
    println(uint64(n))
}

The output will be:

6161047830682206208

It looks like that when float64 change to uint64, the fraction is discarded.

解决方案

The problem here is the representation of constants and floating point numbers.

Constants are represented in arbitrary precision. Floating point numbers are represented using the IEEE 754 standard.

Spec: Constants:

Numeric constants represent values of arbitrary precision and do not overflow.

Spec: Numeric types:

float64     the set of all IEEE-754 64-bit floating-point numbers

In IEEE 754 the double precision which is using 64 bits (float64 in Go) 53 bits are used to store the digits. This means the max digits (max number) that can be represented is the number of digits of 2<<52 which is (1 bit is for sign):

2<<52        : 9007199254740992
Your constant: 6161047830682206209

15.95 digits to be precise (16 digits, but not all values that you can describe with 16 digits, only up to 9007199254740992).

The integer constant you try to put into a variable of type float64 simply does not fit into 52 bits so it has to be rounded and digits (or bits) will be cut off (lost).

You can verify this by printing the original n float64 number:

var n float64 = 6161047830682206209
fmt.Printf("%f
", n)
fmt.Printf("%d
", uint64(n))

Output:

6161047830682206208.000000
6161047830682206208

The problem is not with conversion, the problem is that the float64 value you try to convert is already not equal to the constant you tried to assign to it.

Just for curiosity:

Try the same with a much bigger number: +500 compared to the first const:

n = 6161047830682206709 // +500 compared to first!
fmt.Printf("%f
", n2)
fmt.Printf("%d
", uint64(n2))

Output still the same (the last digits / bits are cut off, +500 included!):

6161047830682206208.000000
6161047830682206208

Try a smaller number whose digits can be represented precisely using 52 bits (less than ~16 digits):

n = 7830682206209
fmt.Printf("%f
", n)
fmt.Printf("%d
", uint64(n))

Output:

7830682206209.000000
7830682206209

Try it on the Go Playground.

这篇关于如何以正确的方式将 float64 数字更改为 uint64?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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