ค่าสูงสุดสำหรับประเภท int ใน Go


132

หนึ่งจะระบุค่าสูงสุดที่แสดงสำหรับunsignedประเภทจำนวนเต็มได้อย่างไร

ฉันต้องการทราบวิธีการเริ่มต้นminในลูปด้านล่างที่คำนวณซ้ำ ๆ ความยาวขั้นต่ำและสูงสุดจาก structs บางอย่าง

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
Victor

คำตอบ:


218

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

ส่วน germane:

ตั้งแต่ประเภทจำนวนเต็มใช้คณิตศาสตร์สมบูรณ์สองคุณสามารถสรุป 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

66
ใช้สิ่งที่มีอยู่ใน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 ศูนย์บิตขึ้นอยู่กับสถาปัตยกรรมเป้าหมายการสร้าง) จากนั้น ^ หน่วย (0) == 1111 ... 1111 ซึ่งทำให้เรามีค่าสูงสุดสำหรับจำนวนเต็มไม่ได้ลงนาม (ทุกคน) ตอนนี้เมื่อคุณกำลังพูดถึงจำนวนเต็มที่ลงนามแล้วบิตแรก (ที่สำคัญที่สุด) จะใช้ในการจัดเก็บเครื่องหมายดังนั้นเพื่อค่าสูงสุด int ลงนาม - เราต้องเปลี่ยนบิตทั้งหมดไปทางขวาซึ่งทำให้เรา ^ uint (0) >> 1 = = 0111 ... 1111 ซึ่งให้จำนวนเต็มบวกสูงสุด
ninjaboy

4
@CharlesL แล้ว int แบบไหนล่ะ?
user960567

1
ฉันรู้ว่ามันใช้เวลาพอสมควร แต่ในกรณีที่มีคนมาที่นี่ในวันนี้และเห็นคำถามของผู้ใช้ @user960567: intประเภทนั้นยาว 32 บิตในระบบ 32 บิตและ 64 บิตในระบบ 64 บิต ดูที่นี่
Christoph Harms-Ensink

73

https://golang.org/ref/spec#Numeric_typesสำหรับข้อ จำกัด ประเภททางกายภาพ

ค่าสูงสุดถูกกำหนดไว้ในแพ็คเกจคณิตศาสตร์ดังนั้นในกรณีของคุณ: math.MaxUint32

ระวังเนื่องจากไม่มีน้ำล้น - การเพิ่มค่าสูงสุดที่ผ่านมาทำให้เกิดปัญหาขึ้น


2
ขอบคุณ ฉันจริงใช้ไม่ได้uint และใช้ไม่ได้ดังนั้นฉันต้องการบางสิ่งบางอย่างที่จะใช้งานที่ตรงกับขนาดของผู้ที่อยู่ในสถาปัตยกรรมทั้งหมด กำหนดพวงของแต่ไม่มีสำหรับอย่างใดอย่างหนึ่งหรือ `int uint32lencapintint32math/const.goMax<type>uint
Mike Samuel

ฉันจะเปลี่ยนเป็น uint32 หรือ unit64 จากนั้นเพื่อให้แน่ใจว่าเป็นแบบพกพาในสถาปัตยกรรม ฉันทำอย่างนั้นกับทุกสิ่งอย่างเคร่งครัด ฉันใช้เวลาหลายปีในการปรับพอร์ต C ระหว่างสถาปัตยกรรมและฉันสามารถพูดได้ว่า "ชัดเจน" จะช่วยได้มากในภายหลัง
ลบ

ขอบคุณ รหัสของฉันตรวจสอบแล้วuint(len(...)) < thing.minLenแต่ฉันไม่รู้ว่าจะuint64(int)เป็นและจะยังคงทำงานตามที่กำหนดไว้หรือไม่
Mike Samuel

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
}

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
รหัสนี้ใช้ไม่ได้ int64int มากเกินไปของทั้งสองซึ่งเป็นสิ่งที่เกิดขึ้นหากคุณไม่ได้พิมพ์ค่าคงที่อย่างชัดเจนก่อนที่จะมีการแก้ไขสายอักขระ ใช้int64(math.MaxInt64)แทนดูstackoverflow.com/questions/16474594/…
domoarigato

3
แต่มิฉะนั้นจะเป็นคำตอบที่ดีกว่าคำตอบที่ได้รับการยอมรับ :)
domoarigato

จะเกิดอะไรขึ้นถ้าคุณใช้ int64 บนเครื่องที่มีขนาด word 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
)

สองขั้นตอนสุดท้ายทำงานเพราะมีการแสดงตัวเลขบวกและลบในคณิตศาสตร์ประกอบสอง The Go ส่วนสเปคภาษาประเภทตัวเลขหมายถึงผู้อ่านที่เกี่ยวข้องบทความวิกิพีเดีย ฉันยังไม่ได้อ่าน แต่ฉันได้เรียนรู้เกี่ยวกับส่วนประกอบสองอย่างจากหนังสือรหัสโดย Charles Petzoldซึ่งเป็นบทนำที่เข้าถึงได้ง่ายมากเกี่ยวกับพื้นฐานของคอมพิวเตอร์และการเข้ารหัส

ฉันใส่รหัสข้างต้น (ลบมากที่สุดของการแสดงความคิดเห็น) ในการเล็ก ๆ น้อย ๆแพคเกจคณิตศาสตร์จำนวนเต็ม


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ขึ้นอยู่กับแพลตฟอร์มที่คุณใช้งาน โดยปกติแล้วจะใช้รุ่นที่ไม่มีการแก้ไขของสิ่งเหล่านี้เฉพาะเมื่อไม่มีความเสี่ยงที่จะเข้าใกล้ค่าสูงสุดเนื่องจากรุ่นที่ไม่มีข้อกำหนดขนาดสามารถใช้ประเภท "ดั้งเดิม" ขึ้นอยู่กับแพลตฟอร์มซึ่งมีแนวโน้มที่จะเร็วกว่า

โปรดทราบว่ามันมีแนวโน้มที่จะ "เร็วขึ้น" เนื่องจากการใช้ชนิดที่ไม่ใช่เจ้าของภาษาบางครั้งต้องใช้การตรวจสอบทางคณิตศาสตร์และขอบเขตเพิ่มเติมเพื่อดำเนินการโดยโปรเซสเซอร์เพื่อเลียนแบบจำนวนเต็มที่ใหญ่กว่าหรือเล็กกว่า โปรดทราบว่าประสิทธิภาพของโปรเซสเซอร์ (หรือโค้ดที่ปรับปรุงแล้วของคอมไพเลอร์) นั้นจะดีกว่าการเพิ่มรหัสตรวจสอบขอบเขตของคุณเองดังนั้นหากมีความเสี่ยงที่จะเกิดขึ้น ใช้เพียงเวอร์ชันขนาดคงที่และปล่อยให้อีมูเลชั่นที่ดีที่สุดจัดการกับ fallout ใด ๆ

เมื่อพูดถึงเรื่องนี้แล้วก็ยังมีบางสถานการณ์ที่มีประโยชน์ที่จะรู้ว่าคุณกำลังทำงานอะไรอยู่

แพ็คเกจ " 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)
}

ขอบคุณ คำเตือนของคุณเกี่ยวกับตัวเลขพื้นเมืองนั้นได้รับการกล่าวถึงอย่างดีและฉันก็ไม่รู้คณิตศาสตร์ / บิต
Mike Samuel

uint อย่างใดอย่างหนึ่ง 32 หรือ 64 บิต int ขนาดเดียวกับ uint ขนาดเหล่านี้จะมีขนาดเท่ากันได้อย่างไรหากมีเครื่องหมายและอีกอันไม่มีขนาด?
พวกเขา

พวกเขามีขนาดบิตเดียวกันพวกเขาไม่มีค่าสูงสุด / ต่ำสุดเหมือนกัน หนึ่งในบิตที่มีขนาดนั้นคือบิตสัญญาณ (คน/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 }
  }
}

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.