2016-06-10 78 views
0

我想了解Go Sqrt的实现,并不能完全理解Float64bits函数的功能。我有一些测试代码和输出如下。为什么ix的价值在这个操作中发生了如此剧烈的变化?Golang Float64bits

package main 

import ("math" 
     "fmt") 

func main() { 

    var x float64 = 4 
    fmt.Printf("The value of x is: %v \n", x) 

    ix := math.Float64bits(x) 
    fmt.Printf("The value of ix is: %v \n", ix) 
    fmt.Printf("The type of ix is: %T \n", ix) 

} 
The value of x is: 4 
The value of ix is: 4616189618054758400 
The type of ix is: uint64 
+0

我相信你正在看的价值是十六进制。如果你知道浮点表示的公式(更多信息在这里https://en.wikipedia.org/wiki/IEEE_floating_point),那么你理论上可以将它应用到该值,它会给你4。 – evanmcdonnal

回答

2

从文档中,它将float64转换为uint64而不更改位,这是位被解释为改变的方式。

这里是Float64bits功能的完整源代码:

func Float64bits(f float64) uint64 { return *(*uint64)(unsafe.Pointer(&f)) } 

不要使用不安全的指针的这种语法招害怕,这是相当常见的Go的源代码(避免复制数据) 。所以,那真的很简单:获取给定float的二进制数据并将其解释为无符号整数。

它变化如此之大的原因是因为浮点数的表示。根据规范,浮点数由符号,指数和尾数组成。

在一个64位浮点上,Sign有1位,指数有11位,尾数有52位。

作为64个比特的浮点数的4表示为:

0b0100 0000 0001 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 
    SEEE EEEE EEEE MMMM MMMM MMMM MMMM MMMM MMMM MMMM MMMM MMMM MMMM MMMM MMMM MMMM 

事实证明,这个值是4616189618054758400如果解释为无符号整数。您将在网上找到很多关于IEEE754的完美教程,以充分理解上述值是如何表示4的。

1

正如documentation所说,函数只是将形成float的数据解释为uint64。

一种IEEE 754 double具有该位布局:

SEEEEEEE EEEEMMMM MMMMMMMM MMMMMMMM MMMMMMMM MMMMMMMM MMMMMMMM MMMMMMMM 

这些是包括64位:

  • 一个符号位S
  • 指数位E
  • 尾数位M

价值4.0等于该位表示:

01000000 00010000 00000000 00000000 00000000 00000000 00000000 00000000 

的详细解释为什么看起来这种方式未免太冗长。关于在这里起关键作用的尾数有一些特殊的规则。现在,我们可以忽略这一点,如果您对数字以IEEE浮点格式表示的所有细节感兴趣,请参阅链接文档。

上述函数没有做任何其他的处理这些64位,就好像它们是uint64一样。最后,这只是投了一堆适合uint64的比特。因此,结果数字与浮点值完全不同。

1

使用fmt.Printf中的%#X格式化十六进制值。和%[1]来表示第一ARG这样的示例代码:

package main 

import "fmt" 
import "math" 

func main() { 
    var x float64 = 4 
    fmt.Println("x =", x) 

    ix := math.Float64bits(x) 
    fmt.Printf("bits: %#X = %[1]v %[1]T\n", ix) 
} 

输出:

x = 4 
bits: 0X4010000000000000 = 4616189618054758400 uint64 

和看到:

https://en.wikipedia.org/wiki/Double-precision_floating-point_formathttps://en.wikipedia.org/wiki/IEEE_floating_point

Why does adding 0.1 multiple times remain lossless?

golang: what does "%b" do in fmt.Printf for float64 and what is Min subnormal positive double in float64 in binary format?

我希望这有助于。