Apa perbedaan antara int dan int64 di Go?

86

Saya memiliki string yang berisi integer (yang telah dibaca dari file).

Saya mencoba mengonversi stringmenjadi intpenggunaan strconv.ParseInt(). ParseIntmengharuskan saya memberikan bitsize (ukuran bit 0, 8, 16, 32, dan 64 sesuai dengan int, int8, int16, int32, dan int64).

Integer yang dibaca dari file berukuran kecil (yaitu harus sesuai dengan int normal). Jika saya memberikan bitsize 0, bagaimanapun, saya mendapatkan hasil tipe int64(mungkin karena saya menjalankan OS 64-bit).

Mengapa ini terjadi? Bagaimana cara mendapatkan int normal? (Jika seseorang mengetahui dengan cepat kapan dan mengapa saya harus menggunakan tipe int yang berbeda, itu akan luar biasa!)

Sunting: Saya dapat mengubah int64 menjadi int normal menggunakan int([i64_var]). Tapi saya masih tidak mengerti mengapa ParseInt()memberi saya int64 ketika saya meminta bitsize 0.

Isaac Dontje Lindell
sumber
2
Gunakan Atoi untuk singkatnya? Juga, apakah fungsi ParseInt Anda menghasilkan kesalahan?
Matt
2
Oke, sekarang saya agak bingung. Jika saya menggunakan Atoi (), itu memberi saya int, dan semuanya berfungsi. Saya menelepon parseInt(s, 0, 0), yang seharusnya menyimpulkan base10 (karena string tidak memiliki awalan dasar). Namun, Atoi adalah singkatan dari pemanggilan parseIntdengan basis 10. Mengapa parameter basis membuat perbedaan pada tipe yang dikembalikan?
Isaac Dontje Lindell
Parameter dasar menentukan bagaimana string input dibaca. Suatu string mungkin terlihat seperti "123" atau "0xBEEFCAKE" atau "1011101" atau "0677". Kesemuanya memiliki arti yang berbeda dan menghasilkan nilai numerik yang berbeda pula. Nilai dasar 0cara kode mencoba untuk mengetahuinya sendiri. Namun terkadang hal ini tidak memungkinkan. 11(desimal) vs 11(biner) mewakili nilai yang sepenuhnya berbeda.
jim
1
Oke, saya rasa yang sebenarnya membuat saya bingung adalah dokumennya. Dokumen untuk Atoi hanya mengatakan bahwa itu hanya "singkatan untuk parseInt(s, 10, 0)". Tapi mengapa Atoi kembali intsaat parseIntmengembalikan int64?
Isaac Dontje Lindell
1
Tidak tahu persis mengapa, saya akan berasumsi bahwa Atoiitu ditambahkan hanya untuk mengakomodasi orang-orang yang lebih akrab dengan C API:int atoi ( const char * str );
jimt

Jawaban:

56
func ParseInt(s string, base int, bitSize int) (i int64, err error)

ParseInt selalu kembali int64

bitSizemendefinisikan rentang nilai. Jika nilai yang sesuai dengan s tidak dapat diwakili oleh bilangan bulat bertanda tangan dari ukuran yang diberikan, err.Err = ErrRange.

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

type int int

int adalah tipe integer bertanda yang berukuran setidaknya 32 bit. Ini adalah tipe yang berbeda, bagaimanapun, dan bukan alias untuk, katakanlah, int32.

http://golang.org/pkg/builtin/#int

Jadi intbisa lebih besar dari 32 bit di masa depan atau pada beberapa sistem sepertiint di C.

Saya kira pada beberapa sistem int64mungkin lebih cepat dariint32 karena sistem itu hanya bekerja dengan 64 bit integer.

Berikut adalah contoh error when bitSize 8

http://play.golang.org/p/_osjMqL6Nj

package main

import (
    "fmt"
    "strconv"
)

func main() {
    i, err := strconv.ParseInt("123456", 10, 8)
    fmt.Println(i, err)
}
Shuriken
sumber
22
Dalam praktiknya, Go biasanya menggunakan int64for intdi GOARCH amd64 dan int32untuk GOARCH int32-bit. Setidaknya dengan kompiler default, saya tidak yakin tentang gccgo. Jadi " intbisa lebih besar dari 32 bit ..." bukan hanya spekulasi, itu sebenarnya lebih mungkin karena target kompilasi 64-bit umumnya dianggap sebagai cabang utama di Go.
LinearZoetrope
12
"Dalam praktiknya, Go biasanya menggunakan int64 untuk int pada amd64 [..]" - lebih tepatnya, int selalu sama dengan ukuran bit prosesor . Jadi pada sistem 64 bit, ini 64 bit, pada sistem 32 bit, ini 32 bit. Saya suka menganggap itu adalah alias int32 atau int64 tergantung pada target kompilasi Anda (bahkan jika itu tidak diimplementasikan sebagai alias, tidak masalah).
zupa
@ zupa apa sumber / referensi untuk "int selalu sama dengan ukuran bit prosesor"?
kapad
29

Paket strconv

func ParseInt

func ParseInt(s string, base int, bitSize int) (i int64, err error)

ParseInt menginterpretasikan string s dalam basis yang diberikan (2 hingga 36) dan mengembalikan nilai yang sesuai i. Jika basis == 0, basis disiratkan oleh awalan string: basis 16 untuk "0x", basis 8 untuk "0", dan basis 10 jika tidak.

Argumen bitSize menentukan jenis integer yang harus cocok dengan hasil. Ukuran bit 0, 8, 16, 32, dan 64 sesuai dengan int, int8, int16, int32, dan int64.

Kesalahan yang dikembalikan ParseInt memiliki tipe konkret * NumError dan menyertakan err.Num = s. Jika s kosong atau berisi digit yang tidak valid, err.Err = ErrSyntax; jika nilai yang sesuai dengan s tidak dapat diwakili oleh bilangan bulat bertanda tangan dari ukuran yang diberikan, err.Err = ErrRange.

ParseIntselalu mengembalikan int64nilai. Tergantung pada bitSize, nilai ini akan masuk ke dalam int, int8, int16, int32, atau int64. Jika nilai tidak dapat diwakili oleh bilangan bulat bertanda dari ukuran yang diberikan oleh bitSize, maka err.Err = ErrRange.

Spesifikasi Bahasa Pemrograman Go

Jenis numerik

Nilai bilangan bulat n-bit adalah n bit lebar dan direpresentasikan menggunakan aritmatika komplemen dua.

int8        the set of all signed  8-bit integers (-128 to 127)
int16       the set of all signed 16-bit integers (-32768 to 32767)
int32       the set of all signed 32-bit integers (-2147483648 to 2147483647)
int64       the set of all signed 64-bit integers (-9223372036854775808 to 9223372036854775807)

Ada juga satu set tipe numerik yang dideklarasikan sebelumnya dengan ukuran khusus implementasi:

uint     either 32 or 64 bits
int      same size as uint

intadalah 32 atau 64 bit, tergantung pada implementasinya. Biasanya 32 bit untuk kompiler 32-bit dan 64 bit untuk kompiler 64-bit.

Untuk mengetahui ukuran sebuah intatau uint, gunakan strconv.IntSize.

Paket strconv

Konstanta

const IntSize = intSize

IntSizeadalah ukuran dalam bit intatau uintnilai.

Sebagai contoh,

package main

import (
    "fmt"
    "runtime"
    "strconv"
)

func main() {
    fmt.Println(runtime.Compiler, runtime.GOARCH, runtime.GOOS)
    fmt.Println(strconv.IntSize)
}

Keluaran:

gc amd64 linux
64
peterSO
sumber
7

strconv.ParseIntdan teman-teman mengembalikan versi 64-bit untuk menjaga API tetap bersih dan sederhana. Jika tidak, seseorang harus membuat versi terpisah untuk setiap jenis pengembalian yang mungkin. Atau kembaliinterface{} , yang kemudian harus melalui pernyataan tipe. Tidak ada satupun yang ideal.

int64dipilih, karena dapat menampung ukuran integer apa pun hingga, dan termasuk, 64-bit yang didukung. Ukuran bit yang Anda berikan ke fungsi tersebut, memastikan bahwa nilainya dijepit dengan benar ke kisaran yang benar. Jadi, Anda cukup melakukan konversi jenis pada nilai yang dikembalikan, untuk mengubahnya menjadi jenis bilangan bulat apa pun yang Anda butuhkan.

Adapun perbedaan antara intdan int64, ini bergantung pada arsitektur.inthanyalah sebuah alias untuk integer 32-bit atau 64-bit, tergantung pada arsitektur yang Anda kompilasi.

Untuk mata yang tajam: Nilai yang dikembalikan adalah bilangan bulat bertanda. Ada strconv.ParseUintfungsi terpisah untuk unsigned integer, yang mengembalikan uint64dan mengikuti alasan yang sama seperti yang dijelaskan di atas.

jimt
sumber
4
Dari apa yang saya lihat sejauh ini, ini hampir benar, kecuali yang menurut saya bukan inthanya sebuah alias - ini sebenarnya tipe yang berbeda. golang.org/pkg/builtin/#int
Isaac Dontje Lindell
Memang. Go tidak benar-benar melakukan tipe aliasing. Sesuatu seperti type int int32harus diperlakukan sebagai tipe yang unik dan terpisah. Terutama karena memungkinkan fungsionalitas baru untuk didefinisikan untuk intjenis melalui penerapan metode baru.
jimt
5

Untuk tujuan Anda, strconv.Atoi() akan lebih nyaman menurut saya.

Jawaban lain sudah cukup lengkap tentang menjelaskan intjenisnya, tetapi saya pikir tautan ke spesifikasi bahasa Go bermanfaat di sini: http://golang.org/ref/spec#Numeric_types

Matt
sumber
0

Dalam Go lang, setiap tipe dianggap sebagai tipe data terpisah yang tidak dapat digunakan secara bergantian dengan tipe dasar. Sebagai contoh,

type CustomInt64 int64

Dalam pernyataan di atas, CustomInt64 dan int64 built-in adalah dua tipe data yang terpisah dan tidak dapat digunakan secara bergantian.

Sama halnya dengan int, int32, dan int64, semuanya adalah tipe data terpisah yang tidak dapat digunakan secara bergantian. Di mana int32 adalah 32 tipe integernya, int64 adalah 64 bit dan ukuran tipe int generik bergantung pada platform. Lebar 32 bit pada sistem 32-bit dan lebar 64-bit pada sistem 64-bit. Jadi kita harus berhati-hati dan spesifik saat menentukan tipe data generik seperti int, uint, dan float. Ini dapat menyebabkan masalah di suatu tempat dalam kode dan akan merusak aplikasi di platform yang berbeda.

Umar Hayat
sumber