Максимальное значение для типа int в Go

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
взгляните на этот фрагмент, int(^uint(0) >> 1) // largest intизвлеченный из golang.org/doc/effective_go.html#printing
Виктор

Ответы:

219

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

Немецкая часть:

Поскольку целочисленные типы используют арифметику дополнения до двух, вы можете вывести константы min / max для 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
nmichaels
источник
68
Используйте те, которые доступны в math: golang.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 что дает нам максимальное значение для целого числа без знака (все единицы). Теперь, когда вы говорите о целых числах со знаком, тогда первый (самый значимый) бит используется для хранения знака, следовательно, до максимального значения int со знаком - нам нужно сдвинуть все биты вправо, что дает нам ^ uint (0) >> 1 = = 0111 ... 1111. Что дает максимальное положительное целое число.
ninjaboy
4
@CharlesL. как насчет только типа int?
user960567
2
Я знаю, что прошло какое-то время, но на всякий случай, если кто-то придет сегодня сюда и увидит вопрос-комментарий @ user960567: intтип имеет длину 32 бита в 32-битной системе и 64 бита в 64-битной системе. Смотрите здесь .
Кристоф Хармс-Энсинк
74

https://golang.org/ref/spec#Numeric_types для ограничений физического типа.

Максимальные значения определены в математическом пакете, поэтому в вашем случае: math.MaxUint32

Следите за тем, чтобы не было переполнения - приращение выше максимума вызывает циклический переход.

Исключен
источник
3
Спасибо. Я на самом деле использую uint, а не uint32. lenИ capиспользование intне int32так что я хочу использовать что - то , что соответствует размеру тех , на всех архитектурах. math/const.goопределяет группу, Max<type>но ни одного для любого uintили `int.
Майк Сэмюэл
Я бы изменил его на uint32 или unit64, чтобы убедиться, что он переносится на разные архитектуры. Я делаю это со всем религиозно. Я прошел через годы адского портирования C между архитектурами и могу сказать, что «явное выражение» значительно поможет позже.
Удалено
1
Спасибо. В моем коде есть проверки, uint(len(...)) < thing.minLenно я не знаю, uint64(int)останется ли определенное поведение и останется ли оно.
Майк Сэмюэл
1
Если вы не знаете, прочтите приведенную выше спецификацию ... в частности, golang.org/doc/go_spec.html#Conversions . Существует тщательное определение «преобразований между числовыми типами».
Аншель Шаффер-Коэн
30

Я бы использовал 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
}

Выход:

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
Этот код не работает. Два int64переполнения int, что происходит, если вы явно не вводите константы перед интерполяцией строк. Используйте int64(math.MaxInt64)вместо этого, см stackoverflow.com/questions/16474594/...
domoarigato
3
Но в остальном это лучший ответ, чем принятый. :)
domoarigato
что произойдет, если вы используете int64 на машине с 32-битным размером слова? в 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
)

Последние два шага работают из-за того, как положительные и отрицательные числа представлены в арифметике с дополнением до двух. Раздел спецификации языка Go о числовых типах отсылает читателя к соответствующей статье в Википедии . Я не читал этого, но я узнал о двух дополнениях из книги Чарльза Петцольда «Код» , которая представляет собой очень доступное введение в основы компьютеров и программирования.

Я поместил приведенный выше код (без большинства комментариев) в небольшой пакет целочисленных математических вычислений .

crantok
источник
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 бита, int того же размера, что и uint. Как они могут быть одного размера, если у одного есть знак, а у другого нет?
themiDdlest
У них одинаковый размер в битах, у них разные максимальные / минимальные значения. Один из битов этого размера - бит знака. ( /2часть - это то, что исключает этот бит из рассмотрения при вычислении размера min / max для int64)
Уилл Палмер
4

Один из способов решить эту проблему - получить начальные точки из самих значений:

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 }
  }
}
SteveMcQwark
источник
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
LoveRick
источник
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
мир
источник
0

Используйте константы, определенные в математическом пакете :

const (
    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
)
М. Леонхард
источник