104

Has anyone got an idea if there is any inbuilt functionality in Go for converting from any one of the numeric types to its binary number form.

For example, if 123 was the input, the string "1111011" would be the output.

Kevin Burke
  • 61,194
  • 76
  • 188
  • 305
cobie
  • 7,023
  • 11
  • 38
  • 60
  • This is done automatically. Decimal numbers are converted and used in binary form. – QuentinUK Dec 14 '12 at 00:21
  • Numbers in a programming language already are stored in binary form. Maybe you meant outputting them in base 2? Or 32-bit two's complement base 2? Of course neither will make sense for floating point numbers, where you want the textual representation of the IEEE whatever format. Or just outputting the raw bit patterns to a stream? – millimoose Dec 14 '12 at 00:39

9 Answers9

148

The strconv package has FormatInt, which accepts an int64 and lets you specify the base.

n := int64(123)

fmt.Println(strconv.FormatInt(n, 2)) // 1111011

DEMO: http://play.golang.org/p/leGVAELMhv

http://golang.org/pkg/strconv/#FormatInt

func FormatInt(i int64, base int) string

FormatInt returns the string representation of i in the given base, for 2 <= base <= 36. The result uses the lower-case letters 'a' to 'z' for digit values >= 10.

I Hate Lazy
  • 47,415
  • 13
  • 86
  • 77
82

See also the fmt package:

n := int64(123)
fmt.Printf("%b", n)  // 1111011
Mark
  • 6,731
  • 1
  • 40
  • 38
15
package main

import . "fmt"

func main(){
    Printf("%d == %08b\n",0,0)
    Printf("%d == %08b\n",1,1)
    Printf("%d == %08b\n",2,2)
    Printf("%d == %08b\n",3,3)
    Printf("%d == %08b\n",4,4)
    Printf("%d == %08b\n",5,5)
}

results in:

0 == 00000000
1 == 00000001
2 == 00000010
3 == 00000011
4 == 00000100
5 == 00000101
sjas
  • 18,644
  • 14
  • 87
  • 92
11

This code works on big integers *big.Int :

x := big.NewInt(123)
s := fmt.Sprintf("%b", x)
// s == "1111011"

because *big.Int implements the fmt.Formatter interface.

Taken from https://stackoverflow.com/a/23317788/871134

Deleplace
  • 6,812
  • 5
  • 28
  • 41
4

An alternate way for the accepted answer would be to simply do

s := fmt.Sprintf("%b", 123)
fmt.Println(s)                 // 1111011

For a more rich representation you can use the unsafe package(strongly discouraged) as

a := int64(123)
byteSliceRev := *(*[8]byte)(unsafe.Pointer(&a))
byteSlice := make([]byte, 8)
for i := 0; i < 8; i++ {
    byteSlice[i] = byteSliceRev[7 - i]
}
fmt.Printf("%b\n", byteSlice)

This works for negative integers too.

Vaibhav Mishra
  • 415
  • 3
  • 10
3

Building on the answer provided by @Mark

Although the OP asked how to print an integer, I often want to look at more then 64 bits worth of data, without my eyes boggling:

/* --- Credit to Dave C in the comments --- */
package main

import (
    "bytes"
    "fmt"
)

func main() {
    fmt.Printf("<%s>\n", fmtBits([]byte{0xDE, 0xAD, 0xBE, 0xEF, 0xF0, 0x0D, 0xDE, 0xAD, 0xBE, 0xEF, 0xF0, 0x0D}))

    // OUTPUT:
    // <11011110 10101101 10111110 11101111 11110000 00001101 11011110 10101101 10111110 11101111 11110000 00001101>
}

func fmtBits(data []byte) []byte {
    var buf bytes.Buffer
    for _, b := range data {
        fmt.Fprintf(&buf, "%08b ", b)
    }
    buf.Truncate(buf.Len() - 1) // To remove extra space
    return buf.Bytes()
}
see this code in play.golang.org
Luke Antins
  • 2,010
  • 1
  • 19
  • 15
  • 2
    If you're going to hard-code to stdout then just output in the loop; if it's a formatting function then have it return `[]byte`. Repeatedly appending to a `string` like that is inefficient, better is to use something like a `bytes.Buffer` (or if only it did leading zeros, using just `strconv.AppendInt` with a plain `[]byte`). Calling `strings.TrimSpace` on each iteration just to handle the single extra space is very inefficient. E.g. something like https://play.golang.org/p/ifobZWv_du on a 1kB input is ~50x faster and uses ~1/50th of the memory. – Dave C Jul 26 '15 at 17:05
  • Efficiency never crossed my mind, but on all counts you are correct and your solution is much better then mine, thanks! Display more then 64-bits worth of data was my goal :) – Luke Antins Jul 26 '15 at 18:26
3

Unsafe pointers must be used to correctly represent negative numbers in binary format.

package main

import (
    "fmt"
    "strconv"
    "unsafe"
)

func bInt(n int64) string {
    return strconv.FormatUint(*(*uint64)(unsafe.Pointer(&n)), 2)
}

func main() {
    fmt.Println(bInt(-1))
}

https://play.golang.org/p/GxXjjWMyC4x

Soslan
  • 102
  • 3
  • 1
    This should be the answer if we want to convert **negative** decimal into *bitwise* representation using two's complement(without `-` sign), not into mathematical binary representation(using - sign). – starriet Mar 19 '22 at 12:20
1

Many above answers do not work if you use negative decimals.

Here is the simplest answer. Also works with negative decimals.

var a int64 = -1
fmt.Printf("%b\n", uint64(a)) // 11111.... (not -1)

(Go playground link)

You can also use fmt.Sprintf instead of fmt.Printf if you want a string variable.

This way, you can convert negative decimal into bitwise representation using two's complement (without - sign), not into mathematical binary representation (using - sign). (As I commented in Soslan's answer.)

(Soslan and Vaibhav's answers also work with negative numbers, using the unsafe package.)

starriet
  • 2,565
  • 22
  • 23
0
package main

import (
    "bytes"
    "encoding/binary"
    "fmt"
    "time"
)

func main() {
    buf := new(bytes.Buffer)
    var x = time.Now().UnixNano()
    err := binary.Write(buf, binary.LittleEndian, x)
    if err != nil {
        fmt.Println("binary.Write failed:", err)
    }
    fmt.Printf("%v", buf.Bytes())
}
Jakobii
  • 508
  • 4
  • 7