Goのint型の最大値


132

unsigned整数型で表現可能な最大値をどのように指定しますか?

minいくつかの構造体から最小長と最大長を繰り返し計算する以下のループで初期化する方法を知りたいです。

var minLen uint = ???
var maxLen uint = 0
for _, thing := range sliceOfThings {
  if minLen > thing.n { minLen = thing.n }
  if maxLen < thing.n { maxLen = thing.n }
}
if minLen > maxLen {
  // If there are no values, clamp min at 0 so that min <= max.
  minLen = 0
}

、比較を通じて初めてとなるようminLen >= n


2
golang.org/doc/effective_go.html#printingint(^uint(0) >> 1) // largest intから抽出されたこのスニペットをご覧ください
Victor

回答:


218

https://groups.google.com/group/golang-nuts/msg/71c307e4d73024ce?pli=1

ジャーマンパート:

整数型は2の補数演算を使用するためint、およびの最小/最大定数値を推測できますuint。例えば、

const MaxUint = ^uint(0) 
const MinUint = 0 
const MaxInt = int(MaxUint >> 1) 
const MinInt = -MaxInt - 1

@CarelZAのコメントによると:

uint8  : 0 to 255 
uint16 : 0 to 65535 
uint32 : 0 to 4294967295 
uint64 : 0 to 18446744073709551615 
int8   : -128 to 127 
int16  : -32768 to 32767 
int32  : -2147483648 to 2147483647 
int64  : -9223372036854775808 to 9223372036854775807

66
で利用可能なものを使用してくださいmathgolang.org/pkg/math/#pkg-constantsは、あなたが望むmath.MaxInt32可能性が高いです。
Charles L.

7
誰かが^ uint(0)と^ uint(0)>> 1の機能を正確に説明できますか?
Arijoon

16
@ Arijoon、^は式のビットを反転することを意味します。したがって、uint(0)== 0000 ... 0000(ビルドターゲットアーキテクチャに応じて正確に32または64のゼロビット)の場合、^ unit(0)== 1111 ... 1111これにより、符号なし整数(すべて1)の最大値が得られます。ここで、符号付き整数について話しているとき、最初の(最上位の)ビットを使用して符号を格納しているため、signed intの最大値に-すべてのビットを右にシフトする必要があります。これにより、^ uint(0)>> 1 = = 0111 ... 1111。これは最大の正の整数を与えます。
ニンジャボーイ2017年

4
@CharlesL。ちょうどint型はどうですか?
user960567

1
私はそれがしばらくの間であることを知っていますが、誰かが今日ここに来て@ user960567の質問コメントを見た場合に備えて:intタイプは32ビットシステムで32ビット長、64ビットシステムで64ビット長です。こちらをご覧ください
Christoph Harms-Ensink

73

物理的なタイプの制限については、https: //golang.org/ref/spec#Numeric_types。

最大値はmathパッケージで定義されているので、あなたの場合:math.MaxUint32

オーバーフローがないことに注意してください。最大値を超えてインクリメントするとラップアラウンドが発生します。


2
ありがとう。実際にはを使用uintしていuint32ますが、は使用していません。lenそしてcap使用しintていないint32私は、すべてのアーキテクチャ上のもののサイズに一致するものを使用したいので。 math/const.goの束を定義しますMax<type>が、どちらかuintまたは `int。
マイクサミュエル

それをuint32またはunit64に変更してから、アーキテクチャ間で移植可能であることを確認します。私はそれをすべて宗教的に行います。私は何年にもわたってアーキテクチャ間でCを移植してきましたが、「明示的である」ことは後でかなり役立つと言えるでしょう。
削除

ありがとう。私のコードはそれをチェックしてuint(len(...)) < thing.minLenいますが、それuint64(int)が定義された動作であるかどうか、そして今後も動作するかどうかはわかりません。
マイクサミュエル

1
わからない場合は、上記のリンクの仕様を確認してください。具体的には、golang.org / doc / go_spec.html#Conversionsをご覧ください。「数値型間の変換」の慎重な定義があります。
Anschel Schaffer-Cohen 2011

29

math最大値と最小値を取得するためにパッケージを使用します:

func printMinMaxValue() {
    // integer max
    fmt.Printf("max int64 = %+v\n", math.MaxInt64)
    fmt.Printf("max int32 = %+v\n", math.MaxInt32)
    fmt.Printf("max int16 = %+v\n", math.MaxInt16)

    // integer min
    fmt.Printf("min int64 = %+v\n", math.MinInt64)
    fmt.Printf("min int32 = %+v\n", math.MinInt32)

    fmt.Printf("max flloat64= %+v\n", math.MaxFloat64)
    fmt.Printf("max float32= %+v\n", math.MaxFloat32)

    // etc you can see more int the `math`package
}

Ouput:

max int64 = 9223372036854775807
max int32 = 2147483647
max int16 = 32767
min int64 = -9223372036854775808
min int32 = -2147483648
max flloat64= 1.7976931348623157e+308
max float32= 3.4028234663852886e+38

1
このコードは機能しません。2つint64のオーバーフローint。これは、文字列補間の前に定数を明示的に入力しない場合に発生します。使用するint64(math.MaxInt64)代わりに、参照stackoverflow.com/questions/16474594/...を
domoarigato

3
しかし、そうでなければ、受け入れられたものよりも良い答えです。:)
domoarigato 2017

32ビットのワードサイズのマシンでint64を使用するとどうなりますか?Cでは、コンパイラーはINT_MINを決定します
segue_segway

12

@nmichaelsが彼の回答で使用したディスカッションスレッドから取得したコードを最初に使用しました。ここで、少し異なる計算を使用します。他の誰かが@Arijoonと同じクエリを持っている場合に備えて、いくつかのコメントを含めました

const (
    MinUint uint = 0                 // binary: all zeroes

    // Perform a bitwise NOT to change every bit from 0 to 1
    MaxUint      = ^MinUint          // binary: all ones

    // Shift the binary number to the right (i.e. divide by two)
    // to change the high bit to 0
    MaxInt       = int(MaxUint >> 1) // binary: all ones except high bit

    // Perform another bitwise NOT to change the high bit to 1 and
    // all other bits to 0
    MinInt       = ^MaxInt           // binary: all zeroes except high bit
)

最後の2つのステップは、正と負の数が2の補数演算でどのように表現されるかによって機能します。数値型のGo言語仕様セクションでは、関連するウィキペディアの記事を参照しています。私はまだ読んでいませんが、Charles Petzold著のコードCodeから2の補数について学びました。

上記のコード(ほとんどのコメントを除く)を小さな整数の数学パッケージに入れました


9

簡単な要約:

import "math/bits"
const (
    MaxUint uint = (1 << bits.UintSize) - 1
    MaxInt int = (1 << bits.UintSize) / 2 - 1
    MinInt int = (1 << bits.UintSize) / -2
)

バックグラウンド:

私が知っていると思いますが、uintタイプは、使用しているプラ​​ットフォームに応じて、uint32またはと同じサイズuint64です。サイズの指定がないバージョンは、プラットフォームによっては「ネイティブ」タイプを使用できるため、最大値に近づくリスクがない場合にのみ、通常、これらのサイズなしバージョンを使用します。

非ネイティブ型を使用すると、大きい整数または小さい整数をエミュレートするために、プロセッサで追加の計算と境界チェックを実行する必要がある場合があるため、「高速」になる傾向があることに注意してください。そのことを念頭に置いて、プロセッサ(またはコンパイラの最適化されたコード)のパフォーマンスは、ほとんどの場合、独自の境界チェックコードを追加するよりも優れていることに注意してください。そのため、それが機能するリスクがある場合、単に固定サイズのバージョンを使用して、最適化されたエミュレーションにそれによるフォールアウトを処理させることを意味します。

それが言われても、あなたが何を使っているのかを知ることが役立ついくつかの状況がまだあります。

パッケージ「math / bits」にはのサイズがビット単位で含まuintれています。最大値を決定するには1、そのビット数から1を引いた数だけシフトします。(1 << bits.UintSize) - 1

の最大値を計算するときはuint、通常、それを明示的にuint(またはそれ以上の)変数に入れる必要があります。そうしないと、デフォルトでその計算を符号付きint(ここで、明らかに、それは適合しないでしょう)、それで:

const MaxUint uint = (1 << bits.UintSize) - 1

それがあなたの質問への直接の答えですが、あなたが興味を持つかもしれないいくつかの関連する計算もあります。

よると仕様uintそしてint常に同じ大きさです。

uint 32ビットまたは64ビット

int 同じサイズ uint

したがって、この定数を使用しての最大値を決定することもできます。intその同じ答えを取り、2それからで除算することにより、1つまり:(1 << bits.UintSize) / 2 - 1

そして、の最小値。その数のビットでintシフト1し、結果をで除算し-2ます。つまり:(1 << bits.UintSize) / -2

要約すれば:

MaxUint: (1 << bits.UintSize) - 1

MaxInt: (1 << bits.UintSize) / 2 - 1

MinInt: (1 << bits.UintSize) / -2

完全な例(以下と同じである必要があります)

package main

import "fmt"
import "math"
import "math/bits"

func main() {
    var mi32 int64 = math.MinInt32
    var mi64 int64 = math.MinInt64

    var i32 uint64 = math.MaxInt32
    var ui32 uint64 = math.MaxUint32
    var i64 uint64 = math.MaxInt64
    var ui64 uint64 = math.MaxUint64
    var ui uint64 = (1 << bits.UintSize) - 1
    var i uint64 = (1 << bits.UintSize) / 2 - 1
    var mi int64 = (1 << bits.UintSize) / -2

    fmt.Printf(" MinInt32: %d\n", mi32)
    fmt.Printf(" MaxInt32:  %d\n", i32)
    fmt.Printf("MaxUint32:  %d\n", ui32)
    fmt.Printf(" MinInt64: %d\n", mi64)
    fmt.Printf(" MaxInt64:  %d\n", i64)
    fmt.Printf("MaxUint64:  %d\n", ui64)
    fmt.Printf("  MaxUint:  %d\n", ui)
    fmt.Printf("   MinInt: %d\n", mi)
    fmt.Printf("   MaxInt:  %d\n", i)
}

ありがとう。ネイティブ数値に関するあなたの警告はよく述べられており、私は数学/ビットについては知りませんでした。
マイクサミュエル

uintと同じサイズの32ビットまたは64ビットのuint。一方に標識があり、もう一方に標識がない場合、これらをどのように同じサイズにすることができますか?
themiDdlest

それらは同じビットサイズを持ち、同じ最大値/最小値を持ちません。そのサイズのビットのうちの1つは、ある符号ビット。(/2一部は、int64の最小/最大のサイズを計算するときに考慮からそのビットを削除するものです)
ウィルパーマー


4

この問題を解決する1つの方法は、値自体から開始点を取得することです。

var minLen, maxLen uint
if len(sliceOfThings) > 0 {
  minLen = sliceOfThings[0].minLen
  maxLen = sliceOfThings[0].maxLen
  for _, thing := range sliceOfThings[1:] {
    if minLen > thing.minLen { minLen = thing.minLen }
    if maxLen < thing.maxLen { maxLen = thing.maxLen }
  }
}

1

軽量パッケージには、それらが含まれています(他のint型の制限と広く使用されている整数関数も含まれています)。

import (
    "fmt"
    "<Full URL>/go-imath/ix"
    "<Full URL>/go-imath/ux"
)
...
fmt.Println(ix.Minimal) // Output: -2147483648 (32-bit) or -9223372036854775808 (64-bit)
fmt.Println(ix.Maximal) // Output: 2147483647 or 9223372036854775807
fmt.Println(ux.Minimal) // Output: 0
fmt.Println(ux.Maximal) // Output: 4294967295 or 18446744073709551615

0
MaxInt8   = 1<<7 - 1
MinInt8   = -1 << 7
MaxInt16  = 1<<15 - 1
MinInt16  = -1 << 15
MaxInt32  = 1<<31 - 1
MinInt32  = -1 << 31
MaxInt64  = 1<<63 - 1
MinInt64  = -1 << 63
MaxUint8  = 1<<8 - 1
MaxUint16 = 1<<16 - 1
MaxUint32 = 1<<32 - 1
MaxUint64 = 1<<64 - 1
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.