Giá trị tối đa cho một kiểu int trong Go


132

Làm thế nào để chỉ định giá trị tối đa đại diện cho một unsignedloại số nguyên?

Tôi muốn biết làm thế nào để khởi tạo mintrong vòng lặp bên dưới mà tính toán lặp lại độ dài tối thiểu và tối đa từ một số cấu trúc.

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
}

Vì vậy, lần đầu tiên thông qua so sánh minLen >= n,.


2
hãy xem đoạn int(^uint(0) >> 1) // largest inttrích này được trích xuất từ golang.org/doc/effective_go.html#printing
Victor

Câu trả lời:


218

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

Phần mầm:

Vì các kiểu số nguyên sử dụng số học bổ sung của hai, bạn có thể suy ra các giá trị hằng số tối thiểu / tối đa cho intuint. Ví dụ,

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

Theo nhận xét của @ 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
Sử dụng những cái có sẵn trong math: golang.org/pkg/math/#pkg-constants , rất có thể bạn sẽ muốn math.MaxInt32.
Charles L.

7
Ai đó có thể giải thích chính xác những gì ^ uint (0) và ^ uint (0) >> 1 làm gì không?
Arijoon

16
@Arijoon, ^ có nghĩa là đảo ngược các bit trong biểu thức vì vậy if: uint (0) == 0000 ... 0000 (chính xác là 32 hoặc 64 bit tùy thuộc vào kiến ​​trúc đích xây dựng) sau đó ^ unit (0) == 1111 ... 1111 cung cấp cho chúng tôi giá trị tối đa cho số nguyên không dấu (tất cả các số nguyên). Bây giờ khi bạn đang nói về số nguyên đã ký thì bit đầu tiên (đáng kể nhất) được sử dụng để lưu trữ dấu do đó thành giá trị tối đa int đã ký - chúng ta cần dịch chuyển tất cả các bit sang bên phải, cung cấp cho chúng tôi ^ uint (0) >> 1 = = 0111 ... 1111. Mà cho số nguyên dương tối đa.
ninjaboy

4
@CharlesL. Còn kiểu int thì sao?
dùng960567

1
Tôi biết đã có lúc, nhưng chỉ trong trường hợp có ai đó đến đây hôm nay và thấy Câu hỏi-Nhận xét của @ user960567: intloại dài 32 bit trên hệ thống 32 bit và dài 64 bit trên hệ thống 64 bit. Xem ở đây .
Christoph Harms-Makeink

73

https://golang.org/ref/spec#Numeric_types cho giới hạn loại vật lý.

Các giá trị tối đa được xác định trong gói toán nên trong trường hợp của bạn: math.MaxUint32

Xem ra vì không có tràn - tăng quá khứ tối đa gây ra sự bao bọc.


2
Cảm ơn. Tôi thực sự đang sử dụng uint, không phải uint32. Các lencapsử dụng intkhông int32vì vậy tôi muốn một cái gì đó sử dụng phù hợp với kích thước của những người trên mọi kiến trúc. math/const.gođịnh nghĩa một bó Max<type>nhưng không có gì cho một trong hai uinthoặc `int.
Mike Samuel

Sau đó, tôi sẽ đổi nó thành uint32 hoặc unit64 để đảm bảo nó di động trên các kiến ​​trúc. Tôi làm điều đó với mọi thứ một cách tôn giáo. Tôi đã trải qua nhiều năm chuyển địa ngục giữa các kiến ​​trúc và tôi có thể nói rằng "rõ ràng" sẽ giúp ích đáng kể sau này.
Đã xóa

Cảm ơn. Mã của tôi đã kiểm tra uint(len(...)) < thing.minLennhưng tôi không biết liệu uint64(int)có và sẽ duy trì hành vi được xác định hay không.
Mike Samuel

1
Nếu bạn không biết thì hãy đọc thông số được liên kết ở trên ... cụ thể là golang.org/doc/go_spec.html#Conversions . Có một định nghĩa cẩn thận về "chuyển đổi giữa các loại số".
Anschel Schaffer-Cohen

29

Tôi sẽ sử dụng mathgói để nhận giá trị tối đa và giá trị tối thiểu:

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
Mã này không hoạt động. int64Int tràn của hai , đó là những gì xảy ra nếu bạn không gõ rõ ràng các hằng trước khi nội suy chuỗi. int64(math.MaxInt64)Thay vào đó, hãy sử dụng stackoverflow.com/questions/16474594/ từ
domoarigato

3
Nhưng nếu không, là một câu trả lời tốt hơn so với câu trả lời được chấp nhận. :)
domoarigato

Điều gì xảy ra nếu bạn sử dụng int64 trên máy có kích thước từ 32 bit? trong C, trình biên dịch quyết định INT_MIN
segue_segway

12

Ban đầu tôi đã sử dụng mã được lấy từ chuỗi thảo luận mà @nmichaels đã sử dụng trong câu trả lời của mình. Bây giờ tôi sử dụng một tính toán hơi khác nhau. Tôi đã bao gồm một số nhận xét trong trường hợp bất kỳ ai khác có cùng truy vấn như @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
)

Hai bước cuối cùng hoạt động vì cách số dương và số âm được biểu thị trong số học bổ sung của hai. Phần đặc tả ngôn ngữ Go trên các loại Số giới thiệu người đọc đến bài viết Wikipedia có liên quan . Tôi chưa đọc nó, nhưng tôi đã học về hai phần bổ sung từ cuốn sách Code của Charles Petzold , đây là phần giới thiệu rất dễ tiếp cận với các nguyên tắc cơ bản của máy tính và mã hóa.

Tôi đặt mã ở trên (trừ hầu hết các ý kiến) vào một gói toán số nguyên nhỏ .


9

Tóm tắt nhanh:

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

Lý lịch:

Như tôi đoán bạn đã biết, các uintloại có kích thước tương tự như một trong hai uint32hoặc uint64, tùy thuộc vào nền tảng mà bạn đang ở trên. Thông thường, người ta sẽ chỉ sử dụng phiên bản chưa được thống nhất trong số này khi không có rủi ro đến gần giá trị tối đa, vì phiên bản không có thông số kích thước có thể sử dụng loại "gốc", tùy thuộc vào nền tảng, có xu hướng nhanh hơn.

Lưu ý rằng nó có xu hướng "nhanh hơn" bởi vì sử dụng loại không phải bản địa đôi khi yêu cầu kiểm tra giới hạn và toán học bổ sung được thực hiện bởi bộ xử lý, để mô phỏng số nguyên lớn hơn hoặc nhỏ hơn. Với ý nghĩ đó, hãy lưu ý rằng hiệu suất của bộ xử lý (hoặc mã được tối ưu hóa của trình biên dịch) hầu như sẽ luôn tốt hơn so với việc thêm mã kiểm tra giới hạn của riêng bạn, vì vậy nếu có bất kỳ rủi ro nào xảy ra, nó có thể gây ra ý nghĩa đơn giản là sử dụng phiên bản kích thước cố định và để cho phần mô phỏng được tối ưu hóa xử lý bất kỳ bụi phóng xạ nào từ đó.

Với điều đó đã được nói, vẫn còn một số tình huống hữu ích để biết những gì bạn đang làm việc với.

Gói " math / bits " chứa kích thước uint, tính bằng bit. Để xác định giá trị tối đa, hãy dịch chuyển 1theo nhiều bit đó, trừ đi 1. tức là:(1 << bits.UintSize) - 1

Lưu ý rằng khi tính giá trị tối đa uint, thông thường bạn sẽ cần đặt nó một cách rõ ràng vào một biến uint(hoặc lớn hơn), nếu không trình biên dịch có thể thất bại, vì nó sẽ mặc định cố gắng gán phép tính đó vào một ký hiệu int(trong đó, như nên rõ ràng, nó sẽ không phù hợp), vì vậy:

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

Đó là câu trả lời trực tiếp cho câu hỏi của bạn, nhưng cũng có một vài tính toán liên quan mà bạn có thể quan tâm.

Theo thông số kỹ thuật , uintintluôn có cùng kích thước.

uint 32 hoặc 64 bit

int cùng kích thước với uint

Vì vậy, chúng ta cũng có thể sử dụng hằng số này để xác định giá trị tối đa của int, bằng cách lấy cùng một câu trả lời và chia cho 2sau đó trừ đi 1. I E:(1 << bits.UintSize) / 2 - 1

Và giá trị tối thiểu của int, bằng cách dịch chuyển 1theo nhiều bit đó và chia kết quả cho -2. I E:(1 << bits.UintSize) / -2

Tóm tắt:

Tối đa: (1 << bits.UintSize) - 1

Tối đa: (1 << bits.UintSize) / 2 - 1

Tối thiểu: (1 << bits.UintSize) / -2

ví dụ đầy đủ (nên giống như dưới đây)

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)
}

Cảm ơn. Thông báo của bạn về số nguyên bản được nêu rõ và tôi không biết về toán học / bit.
Mike Samuel

uint 32 hoặc 64 bit, cùng kích thước với uint. Làm thế nào những cái này có thể có cùng kích thước nếu một cái có dấu và cái kia không?
themiDdlest

Chúng có cùng kích thước bit, chúng không có cùng giá trị tối đa / tối thiểu. Một trong những bit có kích thước đó bit dấu. ( /2phần này là thứ loại bỏ bit đó khỏi sự cân nhắc khi tính toán kích thước tối thiểu / tối đa cho int64)
Will Palmer


4

Một cách để giải quyết vấn đề này là lấy điểm bắt đầu từ chính các giá trị:

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

Một gói nhẹ chứa chúng (cũng như các giới hạn kiểu int khác và một số hàm số nguyên được sử dụng rộng rãi):

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.