2016-06-10 16 views
0

Ich versuche die Go Sqrt Implementierung zu verstehen und kann nicht ganz nachvollziehen, was mit der Float64bits Funktion vor sich geht. Ich habe einen Testcode und eine Ausgabe unten. Warum ändert sich der Wert von ix mit dieser Operation so drastisch?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

Ich glaube, der Wert, den Sie betrachten, ist Hex. Wenn Sie die Formel für Fließkommadarstellungen kennen (mehr Infos hier https://en.wikipedia.org/wiki/IEEE_floating_point), dann könnten Sie sie theoretisch auf diesen Wert anwenden und es würde Ihnen 4 geben. – evanmcdonnal

Antwort

2

Aus der Dokumentation konvertiert es die float64 in eine uint64, ohne die Bits zu ändern, es ist die Art, wie die Bits interpretiert werden, die sich ändern. Hier

ist der vollständige Quellcode der Float64bits Funktion:

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

Sie sich nicht von dieser Syntax Trick mit einem unsicheren Zeiger Angst, es ist durchaus üblich in Go Quellcode (verhindert das Kopieren der Daten) . Also, das ist wirklich so einfach: nimm die Binärdaten des gegebenen Floats und interpretiere sie als unsigned Integer.

Der Grund, warum es so viel ändert, ist wegen der Darstellung von Fließkommazahlen. Gemäß der Spezifikation besteht eine Gleitkommazahl aus einem Zeichen, einem Exponenten und einer Mantissa.

Auf einem 64-Bit-Float gibt es 1 Bit für das Vorzeichen, 11 Bit für den Exponenten und 52 Bit für die Mantisse.

Die Darstellung von 4 als eine Gleitkommazahl auf 64 Bits beträgt:

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 

Es stellt sich heraus, dass dieser Wert 4616189618054758400 als unsigned integer wenn interpretiert wird. Im Internet finden Sie viele großartige Tutorials zum IEEE754, um zu verstehen, wie der obige Wert eine Darstellung von 4 darstellt.

1

Wie die documentation sagt, interpretiert die Funktion nur die Daten, die den Schwimmer als uint64 bilden.

Ein IEEE 754 double hat dieses Bit Layout:

SEEEEEEE EEEEMMMM MMMMMMMM MMMMMMMM MMMMMMMM MMMMMMMM MMMMMMMM MMMMMMMM 

Diese 64 Bits sind, bestehend aus:

  • ein Vorzeichenbit S
  • Exponentenbits E
  • Mantissenbits M

Der Wert 4.0 gleich dieser Bit-Darstellung:

01000000 00010000 00000000 00000000 00000000 00000000 00000000 00000000 

Eine detaillierte Erklärung, warum aussieht, ist auf diese Weise zu lang sein würde. Es gibt einige spezielle Regeln bezüglich der Mantisse, die hier eine Schlüsselrolle spielen. Wir können das jetzt einfach ignorieren, bitte sehen Sie sich das verlinkte Dokument an, wenn Sie an all den schmutzigen Details interessiert sind, wie Zahlen im IEEE-Float-Format dargestellt werden.

Die obige Funktion macht nichts anderes als die Behandlung dieser 64 Bits, als ob sie eine uint64 wären. Am Ende ist dies nur ein Haufen Bits, die zufällig in eine uint64 passen. Daher ist die resultierende Zahl völlig anders als der Gleitkommawert.

1

Verwenden Sie% # X in fmt.Printf, um den Hex-Wert zu formatieren. und% [1], um sich auf dem ersten Arg- wie dieser Beispielcode:

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) 
} 

output:

x = 4 
bits: 0X4010000000000000 = 4616189618054758400 uint64 

und sehen:

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?

Ich hoffe, das hilft.