Go'da int ve int64 arasındaki fark nedir?


86

Tam sayı içeren bir dizem var (bir dosyadan okunmuş).

Ben dönüştürmek için çalışıyorum stringbir karşı intkullanarak strconv.ParseInt(). ParseIntbir bit boyutu sağlamamı gerektirir (bit boyutları 0, 8, 16, 32 ve 64, int, int8, int16, int32 ve int64'e karşılık gelir).

Dosyadan okunan tamsayı küçüktür (yani, normal bir tamsayıya sığmalıdır). Bununla birlikte, 0 bit boyutunu geçersem, türün sonucunu alırım int64(muhtemelen 64 bit işletim sisteminde çalıştığım için).

Bu neden oluyor? Nasıl normal int elde ederim? (Birisi farklı int türlerini ne zaman ve neden kullanmam gerektiğine dair hızlı bir ön bilgiye sahipse, bu harika olurdu!)

Düzenleme: kullanarak int64'ü normal int'e dönüştürebilirim int([i64_var]). Ama yine de ParseInt()0 bitlik bir boyut istediğimde neden bana bir int64 verdiğini anlamıyorum.


2
Kullanım atoi kısalık için? Ayrıca, ParseInt işleviniz bir hata mı döndürüyor?
Matt

2
Tamam, şimdi biraz kafam karıştı. Atoi () kullanırsam, bana bir int verir ve her şey çalışır. Ben arıyordum parseInt(s, 0, 0), bu da base10 sonucunu çıkarmalı (dizenin temel öneki olmadığı için). Ancak, Atoi, parseInt10 tabanında çağrı yapmanın kısaltmasıdır . Temel parametre döndürülen türde neden bir fark yaratır?
Isaac Dontje Lindell

Temel parametre, girdi dizesinin nasıl okunacağını belirler. Dize "123" veya "0xBEEFCAKE" veya "1011101" veya "0677" gibi görünebilir. Hepsi farklı bir anlama sahiptir ve farklı bir sayısal değer verir. Temel değer 0, kodun bunu kendi kendine anlamaya çalıştığı anlamına gelir. Ancak bazen bu mümkün değildir. 11(ondalık) vs 11(ikili) tamamen farklı değerleri temsil eder.
jimt

1
Tamam, sanırım gerçekten kafam karıştı, dokümanlar. Atoi için dokümanlar sadece bunun "için bir kısaltma" olduğunu söylüyor parseInt(s, 10, 0). Ama neden sonra atoi çıkmıyor intise parseIntdönüş Int64?
Isaac Dontje Lindell

1
Tam olarak nedenini bilmeden, Atoibunun C API'ye daha aşina olan kişileri barındırmak için eklendiğini varsayacağım :int atoi ( const char * str );
jimt

Yanıtlar:


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

ParseInt her zaman döndürür int64

bitSizedeğer aralığını tanımlar. S'ye karşılık gelen değer, verilen büyüklükte işaretli bir tamsayı ile temsil edilemiyorsa, err.Err = ErrRange.

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

type int int

int, boyutu en az 32 bit olan işaretli bir tamsayı türüdür. Bununla birlikte, farklı bir türdür ve örneğin int32 için bir takma ad değildir.

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

Dolayısıyla int, gelecekte veya intC'deki gibi bazı sistemlerde 32 bitten daha büyük olabilir .

Sanırım bazı sistemlerde int64daha hızlı olabilir int32çünkü bu sistem sadece 64 bit tamsayılarla çalışır.

İşte bitSize8 olduğunda hata örneği

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

package main

import (
    "fmt"
    "strconv"
)

func main() {
    i, err := strconv.ParseInt("123456", 10, 8)
    fmt.Println(i, err)
}

22
Uygulamada, Git genellikle kullandığı int64için intbir amd64'tür GOARCH ve int32için int32 bit GOARCHes üzerinde. En azından varsayılan derleyiciyle gccgo hakkında emin değilim. Yani " int32 bitten büyük olabilir ..." sadece spekülasyon değildir, aslında 64-bit derleme hedeflerinin genellikle Go'daki ana dal olarak kabul edilmesinden dolayı oldukça muhtemeldir.
LinearZoetrope

12
"Pratikte, Go genellikle bir amd64 [..] üzerinde int için int64 kullanır" - daha doğrusu, int her zaman işlemcinin bit boyutuna eşittir . Yani 64 bit sistemlerde 64 bit, 32 bit sistemlerde 32 bit. Derleme hedefinize bağlı olarak int32 veya int64'ün bir takma adı olduğunu düşünmeyi seviyorum (takma ad olarak uygulanmasa bile önemli değil).
zupa

@zupa "int her zaman işlemci bit boyutuna eşittir" için kaynak / başvuru nedir?
kapad

29

Paket strconv

func ParseInt

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

ParseInt, verilen tabandaki (2 ila 36) bir s dizesini yorumlar ve karşılık gelen i değerini döndürür. Taban == 0 ise, taban, dizenin öneki ile ifade edilir: "0x" için 16 tabanı, "0" için 8 tabanı ve aksi takdirde 10 tabanı.

BitSize argümanı, sonucun sığması gereken tamsayı türünü belirtir. 0, 8, 16, 32 ve 64 bit boyutları int, int8, int16, int32 ve int64'e karşılık gelir.

ParseInt'in döndürdüğü hatalar somut * NumError türüne sahiptir ve err.Num = s içerir. S boşsa veya geçersiz rakamlar içeriyorsa, err.Err = ErrSyntax; s'ye karşılık gelen değer verilen büyüklükte işaretli bir tamsayı ile temsil edilemiyorsa, err.Err = ErrRange.

ParseInther zaman bir int64değer döndürür . Bağlı bitSizebu değer sığacak int, int8, int16, int32, veya int64. Değer, tarafından verilen boyutta işaretli bir tamsayı ile temsil edilemiyorsa bitSize, o zaman err.Err = ErrRange.

Go Programlama Dili Spesifikasyonu

Sayısal türler

Bir n bitlik tamsayının değeri n bit genişliğindedir ve ikinin tamamlayıcı aritmetiği kullanılarak temsil edilir.

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)

Ayrıca, uygulamaya özel boyutlara sahip önceden bildirilmiş bir dizi sayısal tür vardır:

uint     either 32 or 64 bits
int      same size as uint

intuygulamaya bağlı olarak 32 veya 64 bittir. Genellikle 32 bit derleyiciler için 32 bit ve 64 bit derleyiciler için 64 bittir.

Bir intveya nin boyutunu bulmak için uintkullanın strconv.IntSize.

Paket strconv

Sabitler

const IntSize = intSize

IntSizebir intveya uintdeğerin bit cinsinden boyutudur .

Örneğin,

package main

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

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

Çıktı:

gc amd64 linux
64

7

strconv.ParseIntve arkadaşlar API'yi temiz ve basit tutmak için 64 bit sürümleri döndürür. Aksi takdirde, olası her dönüş türü için ayrı sürümler oluşturmak gerekir. Veya interface{}daha sonra bir tür iddiasından geçmesi gereken dönüş . Hiçbiri ideal değil.

int64desteklenen 64 bit dahil olmak üzere herhangi bir tamsayı boyutunu tutabildiğinden seçilir. İşleve geçirdiğiniz bit boyutu, değerin doğru aralığa uygun şekilde sabitlenmesini sağlar. Böylece, istediğiniz tam sayı türüne dönüştürmek için döndürülen değer üzerinde bir tür dönüşümü yapabilirsiniz.

Arasındaki fark ise intve int64bu mimari bağlıdır. intderleme yaptığınız mimariye bağlı olarak, 32-bit veya 64-bit tamsayı için bir takma addır.

Ayırt edici göz için: Dönen değer işaretli bir tamsayıdır. strconv.ParseUintİşaretsiz tamsayılar için, uint64yukarıda açıklandığı gibi aynı mantığı döndüren ve izleyen ayrı bir işlev vardır .


4
Şimdiye kadar gördüğüm kadarıyla, bu neredeyse doğru, ancak intsadece bir takma ad olduğunu düşünmüyorum - aslında farklı bir tür. golang.org/pkg/builtin/#int
Isaac Dontje Lindell

Aslında. Go, gerçekten tür örtüşme yapmaz. Benzer bir şey type int int32, benzersiz ve ayrı bir tür olarak ele alınmalıdır. Özellikle int, yeni yöntemlerin uygulanması yoluyla tür için yeni işlevselliğin tanımlanmasına izin verdiği için .
jimt


0

Go lang'de her tür, temel türle birbirinin yerine kullanılamayan ayrı veri türü olarak kabul edilir. Örneğin,

type CustomInt64 int64

Yukarıdaki bildirimde, CustomInt64 ve yerleşik int64 iki ayrı veri türüdür ve birbirinin yerine kullanılamaz.

Aynı durum int, int32 ve int64 için de geçerlidir, bunların tümü birbirinin yerine kullanılamayan ayrı veri türleridir. İnt32'nin tamsayı türü 32 olduğunda, int64 64 bittir ve genel int türünün boyutu platforma bağlıdır. 32 bitlik bir sistemde 32 bit genişliğinde ve 64 bitlik bir sistemde 64 bit genişliğindedir. Bu yüzden int, uint ve float gibi genel veri türlerini belirlerken dikkatli ve spesifik olmalıyız. Kodun bir yerinde soruna neden olabilir ve farklı bir platformdaki uygulamayı çökertebilir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.