dongwuli5105 2015-06-17 16:25
浏览 719
已采纳

如何以正确的方式将float64数字更改为uint64?

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.

  • 写回答

1条回答 默认 最新

  • dongle19863 2015-06-17 16:42
    关注

    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.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 javaweb项目无法正常跳转
  • ¥15 VMBox虚拟机无法访问
  • ¥15 skd显示找不到头文件
  • ¥15 机器视觉中图片中长度与真实长度的关系
  • ¥15 fastreport table 怎么只让每页的最下面和最顶部有横线
  • ¥15 R语言卸载之后无法重装,显示电脑存在下载某些较大二进制文件行为,怎么办
  • ¥15 java 的protected权限 ,问题在注释里
  • ¥15 这个是哪里有问题啊?
  • ¥15 关于#vue.js#的问题:修改用户信息功能图片无法回显,数据库中只存了一张图片(相关搜索:字符串)
  • ¥15 texstudio的问题,