golang how can I convert uint64 to int64? [duplicate] - go

This question already has answers here:
Convert uint64 to int64 without loss of information
(3 answers)
Closed 5 years ago.
anyone can help me? converting uint64 to int64 pls
//fmt.Println(int64(18446744073709551615))
//constant 18446744073709551615 overflows int64
var x uint64 = 18446744073709551615
var y int64 = int64(x)
fmt.Println(y) //-1
//just like(c)signed long long
//anyone can help me pls!
//How can I using like this?
// -9223372036854775808 +9223372036854775807
func BytesToInt(b []byte) int {
bytesBuffer := bytes.NewBuffer(b)
var tmp int32
binary.Read(bytesBuffer, binary.BigEndian, &tmp)
return int(tmp)
}

What you are asking (to store 18,446,744,073,709,551,615 as an int64 value) is impossible.
A unit64 stores positive integers and has 64 bits available to hold information. It can therefore store any positive integer between 0 and 18,446,744,073,709,551,615 (2^64-1).
An int64 uses one bit to hold the sign, leaving 63 bits to hold information about the number. It can store any value between -9,223,372,036,854,775,808 and +9,223,372,036,854,775,807 (-2^63 and 2^63-1).
Both types can hold 18,446,744,073,709,551,616 unique integers, it is just that the uint64 range starts at zero, where as the int64 values straddle zero.
To hold 18,446,744,073,709,551,615 as a signed integer would require 65 bits.
In your conversion, no information from the underlying bytes is lost. The difference in the integer values returned is due to how the the two types interpret and display the values.
uint64 will display a raw integer value, whereas int64 will use two's complement.
var x uint64 = 18446744073709551615
var y int64 = int64(x)
fmt.Printf("uint64: %v = %#[1]x, int64: %v = %#x\n", x, y, uint64(y))
// uint64: 18446744073709551615 = 0xffffffffffffffff
// int64: -1 = 0xffffffffffffffff
x -= 100
y -= 100
fmt.Printf("uint64: %v = %#[1]x, int64: %v = %#x\n", x, y, uint64(y))
// uint64: 18446744073709551515 = 0xffffffffffffff9b
// int64: -101 = 0xffffffffffffff9b
https://play.golang.com/p/hlWqhnC9Dh

Related

Why is the .Bytes() value of a 0 big.Int an empty slice?

Why does calling .Bytes() on a zero value big.Int return a slice of length 0?
// uint64
var x uint64
xb := make([]byte, 8)
binary.BigEndian.PutUint64(xb, x)
// [0 0 0 0 0 0 0 0]
fmt.Println(xb)
// uint8
var y uint8
yb := []byte{byte(y)}
// [0]
fmt.Println(yb)
// big.Int
z := big.Int{}
zb := z.Bytes()
// [] Why is this an empty slice and not [0]
fmt.Println(zb)
big.Int stores the absolute value of the number it represents in a slice. big.Int documents that "the zero value for an Int represents the value 0". So in the zero value (which represents 0) the slice will be empty (zero value for slices is nil and the length of a nil slice is 0).
The reasoning is simple: in cases where you don't use a big.Int value, it won't require allocation for the slice. Zero is the most special and probably the most frequent value, using this simple trick is a "no-brainer" optimization.
See related question: Is there another way of testing if a big.Int is 0?

Why range and subscription of a string produce different types?

import (
"fmt"
"reflect"
)
func main() {
s := "hello" // Same results with s := "世界"
for _, x := range s {
kx := reflect.ValueOf(x).Kind()
fmt.Printf("Type of x is %v\n", kx)
break
}
y := s[0]
ky := reflect.ValueOf(y).Kind()
fmt.Printf("Type of y is %v\n", ky)
}
// Type of x is int32
// Type of y is uint8
I was surprised to learn that I would get a different type if I use string subscription versus getting it via range.
Edit: I just realized that even s is a Unicode string, the type of y is always byte. This also means indexing into a string is unsafe unless it's an ASCII string.
For statements with range clause: (Link)
For a string value, the "range" clause iterates over the Unicode code points in the string starting at byte index 0. On successive iterations, the index value will be the index of the first byte of successive UTF-8-encoded code points in the string, and the second value, of type rune, will be the value of the corresponding code point. If the iteration encounters an invalid UTF-8 sequence, the second value will be 0xFFFD, the Unicode replacement character, and the next iteration will advance a single byte in the string.
Now let's look at the types: (Link)
// byte is an alias for uint8 and is equivalent to uint8 in all ways. It is
// used, by convention, to distinguish byte values from 8-bit unsigned
// integer values.
type byte = uint8
// rune is an alias for int32 and is equivalent to int32 in all ways. It is
// used, by convention, to distinguish character values from integer values.
type rune = int32
So this explains why int32 is for a rune, and uint8 is for a byte.
Here's some code to make the point clear. I've added some code and changed the
string to make it better. I hope the comments are self-explanatory. Also, I'd recommend reading: https://blog.golang.org/strings as well.
package main
import (
"fmt"
"reflect"
)
func main() {
// Changed the string for better understanding
// Each character is not of single byte
s := "日本語"
// Range over the string, where x is a rune
for _, x := range s {
kx := reflect.ValueOf(x).Kind()
fmt.Printf(
"Type of x is %v (%c)\n",
kx,
x, // Expected (rune)
)
break
}
// Indexing (First byte of the string)
y := s[0]
ky := reflect.ValueOf(y).Kind()
fmt.Printf(
"Type of y is %v (%c)\n",
ky,
y,
/*
Uh-oh, not expected. We are getting just the first byte
of a string and not the full multi-byte character.
But we need '日' (3 byte character).
*/
)
// Indexing (First rune of the string)
z := []rune(s)[0]
kz := reflect.ValueOf(z).Kind()
fmt.Printf(
"Type of z is %v (%c)\n",
kz,
z, // Expected (rune)
)
}
Sample output:
Type of x is int32 (日)
Type of y is uint8 (æ)
Type of z is int32 (日)
Note: In case your terminal is not showing the same output; there might be some issue with character encoding settings. So, changing that might help.

Why these two structs have different size in the memory?

Suppose I have these two structs:
package main
import (
"fmt"
"unsafe"
)
type A struct {
int8
int16
bool
}
type B struct {
int8
bool
int16
}
func main() {
fmt.Println(unsafe.Sizeof(A{}), unsafe.Sizeof(B{})) // 6 4
}
Size of A is 6 bytes. however, the size of B is 4 bytes.
I assume that it's related to their layout in the memory, but I'm not sure I understand why it's behave like this.
Isn't something that the compiler can detect and optimize? (rearrange the fields order)
Link to the code
Padding due to alignment.
The Go Programming Language Specification
Size and alignment guarantees
For the numeric types, the following sizes are guaranteed:
type size in bytes
byte, uint8, int8 1
uint16, int16 2
uint32, int32, float32 4
uint64, int64, float64, complex64 8
complex128 16
The following minimal alignment properties are guaranteed:
For a variable x of any type: unsafe.Alignof(x) is at least 1.
For a variable x of struct type: unsafe.Alignof(x) is the largest of all the values unsafe.Alignof(x.f) for each field f of x, but at least
1.
For a variable x of array type: unsafe.Alignof(x) is the same as the alignment of a variable of the array's element type.
A struct or array type has size zero if it contains no fields (or
elements, respectively) that have a size greater than zero. Two
distinct zero-size variables may have the same address in memory.
For example,
package main
import (
"fmt"
"unsafe"
)
type A struct {
x int8
y int16
z bool
}
type B struct {
x int8
y bool
z int16
}
func main() {
var a A
fmt.Println("A:")
fmt.Println("Size: ", unsafe.Sizeof(a))
fmt.Printf("Address: %p %p %p\n", &a.x, &a.y, &a.z)
fmt.Printf("Offset: %d %d %d\n", unsafe.Offsetof(a.x), unsafe.Offsetof(a.y), unsafe.Offsetof(a.z))
fmt.Println()
var b B
fmt.Println("B:")
fmt.Println("Size: ", unsafe.Sizeof(b))
fmt.Printf("Address: %p %p %p\n", &b.x, &b.y, &b.z)
fmt.Printf("Offset: %d %d %d\n", unsafe.Offsetof(b.x), unsafe.Offsetof(b.y), unsafe.Offsetof(b.z))
}
Playground: https://play.golang.org/p/_8yDMungDg0
Output:
A:
Size: 6
Address: 0x10410020 0x10410022 0x10410024
Offset: 0 2 4
B:
Size: 4
Address: 0x10410040 0x10410041 0x10410042
Offset: 0 1 2
You may be matching an external struct, perhaps in another language. It's up to you to tell the compiler what you want. The compiler doesn't guess.

No panic when converting int to uint?

I'm confused about the following type conversion. I would expect both uint conversions to panic.
a := -1
_ = uint(a) // why no panic?
_ = uint(-1) // panics: constant -1 overflows uint
Why doesn't it panic in line 2?
https://play.golang.org/p/jcfDL8km2C
As mentioned in issue 6923:
T(c) where T is a type and c is a constant means to treat c as having type T rather than one of the default types.
It gives an error if c can not be represented in T, except that for float and complex constants we quietly round to T as long as the value is not too large.
Here:
const x uint = -1
var x uint = -1
This doesn't work because -1 cannot be (implicitly) converted to a uint.
_ = uint(a) // why no panic?
Because a is not an untyped constant, but a typed variable (int). See Playground and "what's wrong with Golang constant overflows uint64":
package main
import "fmt"
func main() {
a := -1
_ = uint(a) // why no panic?
var b uint
b = uint(a)
fmt.Println(b)
// _ = uint(-1) // panics: main.go:7: constant -1 overflows uint
}
Result: 4294967295 (on 32-bits system) or 18446744073709551615 (on 64-bits system), as commented by starriet
That are specific rules for the conversion of non-constant numeric values:
When converting between integer types, if the value is a signed integer, it is sign extended to implicit infinite precision; otherwise it is zero extended.
It is then truncated to fit in the result type's size.

Convert an integer to a float number

How do I convert an integer value to float64 type?
I tried
float(integer_value)
But this does not work. And can't find any package that does this on Golang.org
How do I get float64 values from integer values?
There is no float type. Looks like you want float64. You could also use float32 if you only need a single-precision floating point value.
package main
import "fmt"
func main() {
i := 5
f := float64(i)
fmt.Printf("f is %f\n", f)
}
Just for the sake of completeness, here is a link to the golang documentation which describes all types. In your case it is numeric types:
uint8 the set of all unsigned 8-bit integers (0 to 255)
uint16 the set of all unsigned 16-bit integers (0 to 65535)
uint32 the set of all unsigned 32-bit integers (0 to 4294967295)
uint64 the set of all unsigned 64-bit integers (0 to 18446744073709551615)
int8 the set of all signed 8-bit integers (-128 to 127)
int16 the set of all signed 16-bit integers (-32768 to 32767)
int32 the set of all signed 32-bit integers (-2147483648 to 2147483647)
int64 the set of all signed 64-bit integers (-9223372036854775808 to 9223372036854775807)
float32 the set of all IEEE-754 32-bit floating-point numbers
float64 the set of all IEEE-754 64-bit floating-point numbers
complex64 the set of all complex numbers with float32 real and imaginary parts
complex128 the set of all complex numbers with float64 real and imaginary parts
byte alias for uint8
rune alias for int32
Which means that you need to use float64(integer_value).
just do these
package main
func main(){
a:= 70
afloat := float64(a)
fmt.Printf("type of a is %T\n", a) // will int
fmt.Printf("type of a is %T\n", afloat) //will float64
}
intutils.ToFloat32
// ToFloat32 converts a int num to a float32 num
func ToFloat32(in int) float32 {
return float32(in)
}
// ToFloat64 converts a int num to a float64 num
func ToFloat64(in int) float64 {
return float64(in)
}
Proper parentheses placement is key:
package main
import (
"fmt"
)
func main() {
var payload uint32
var fpayload float32
payload = 1320
// works
fpayload = float32(payload) / 100.0
fmt.Printf("%T = %d, %T = %f\n", payload, payload, fpayload, fpayload)
// doesn't work
fpayload = float32(payload / 100.0)
fmt.Printf("%T = %d, %T = %f\n", payload, payload, fpayload, fpayload)
}
results:
uint32 = 1320, float32 = 13.200000
uint32 = 1320, float32 = 13.000000
The Go Playground
Type Conversions T() where T is the desired datatype of the result are quite simple in GoLang.
In my program, I scan an integer i from the user input, perform a type conversion on it and store it in the variable f. The output prints the float64 equivalent of the int input. float32 datatype is also available in GoLang
Code:
package main
import "fmt"
func main() {
var i int
fmt.Println("Enter an Integer input: ")
fmt.Scanf("%d", &i)
f := float64(i)
fmt.Printf("The float64 representation of %d is %f\n", i, f)
}
Solution:
>>> Enter an Integer input:
>>> 232332
>>> The float64 representation of 232332 is 232332.000000

Resources