Максимальне значення для типу 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
Віктор

Відповіді:


218

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

Німецька частина:

Оскільки цілі типи використовують арифметику комплементу двох, ви можете зробити висновки про мінімальні постійні значення для 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
Використовуйте ті, які доступні на math: golang.org/pkg/math/#pkg-constants , які ви хотіли б math.MaxInt32швидше за все.
Чарльз Л.

7
Чи може хтось точно пояснити, що роблять ^ uint (0) та ^ uint (0) >> 1?
Arijoon

16
@Arijoon, ^ означає інвертувати біти у виразі, так що якщо: uint (0) == 0000 ... 0000 (рівно 32 або 64 нульових біта залежно від архітектури цільової збірки), то ^ одиниця (0) == 1111 ... 1111 що дає нам максимальне значення для непідписаного цілого числа (усі). Тепер, коли ви говорите про підписане ціле число, тоді перший (найзначніший) біт використовується для зберігання знаку, тому до максимального значення підписаного int - нам потрібно змістити всі біти вправо, що дає нам ^ uint (0) >> 1 = = 0111 ... 1111. Що дає максимальне додатне ціле число.
ніндзябой

4
@CharlesL. що про тип int?
user960567

1
Я знаю, що пройшло вже якийсь час, але на всякий випадок, коли хтось сьогодні приходить сюди і побачить питання @ user960567 «Запитання-коментар»: intтип має 32 біти в 32-бітній системі і 64 біт на 64-бітній системі. Дивіться тут .
Крістоф Хармс-Енсінк

73

https://golang.org/ref/spec#Numeric_types для обмежень фізичного типу.

Максимальні значення визначені в математичному пакеті, так що у вашому випадку: 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

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
}

Вихід:

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«s переповнення ІНТ, що це те , що станеться , якщо ви явно не вводити константи раніше в інтерполяції рядків. Використовуйте 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 щодо числових типів спрямовує читача до відповідної статті Вікіпедії . Я цього не читав, але я дізнався про доповнення двох із книги Код Чарльза Петцольда , яка є дуже доступним ознайомленням з основами комп'ютерів та кодування.

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


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, залежно від платформи, на якій ви знаходитесь. Зазвичай можна використовувати нерозмірну версію цих версій лише тоді, коли немає ризику наблизитись до максимального значення, оскільки версія без специфікації розміру може використовувати "нативний" тип, залежно від платформи, яка, як правило, швидша.

Зауважте, що це, як правило, "швидше", тому що використання нетипового типу іноді вимагає додаткової математики та перевірки меж, яку повинен виконувати процесор, щоб імітувати більший чи менший ціле число. Зважаючи на це, майте на увазі, що продуктивність процесора (або оптимізованого коду компілятора) майже завжди буде кращою, ніж додавання власного коду перевірки меж, тому, якщо є якийсь ризик його вступу, він може створити сенс просто використовувати версію фіксованого розміру, і дозволити оптимізованій емуляції обробляти будь-які випадання з цього.

Зважаючи на це, є ще деякі ситуації, коли корисно знати, з чим ти працюєш.

Пакет " математика / біт " містить розмір 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. Як вони можуть бути однакового розміру, якщо один має знак, а інший - ні?
themiDlelest

Вони мають однаковий розмір бітів, не мають однакових максимальних / мінімальних значень. Одним з бітів такого розміру є бітовий знак. ( /2частина полягає в тому, що знімає цей біт з врахування при розрахунку розміру хв / макс для 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 }
  }
}

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.