Different output from the same Go program - go

Here is my Go code: http://play.golang.org/p/CDUagFZ-rk
package main
import "fmt"
func main() {
var max int = 0
for i := 0; i < 1000000; i++ {
var len int = GetCollatzSeqLen(i)
if len > max {
max = len
}
}
fmt.Println(max)
}
func GetCollatzSeqLen(n int) int {
var len int = 1
for n > 1 {
len++
if n%2 == 0 {
n = n / 2
} else {
n = 3*n + 1
}
}
return len
}
On my local machine, when I run the program, I get 525 as the output. When I run it on the Go Playground, the output is 476.
I am wondering what's different.

It's because of the implementation-specific size of int, 32 or 64 bits. Use int64 for consistent results. For example,
package main
import "fmt"
func main() {
var max int64 = 0
for i := int64(0); i < 1000000; i++ {
var len int64 = GetCollatzSeqLen(i)
if len > max {
max = len
}
}
fmt.Println(max)
}
func GetCollatzSeqLen(n int64) int64 {
var len int64 = 1
for n > 1 {
len++
if n%2 == 0 {
n = n / 2
} else {
n = 3*n + 1
}
}
return len
}
Output:
525
Playground: http://play.golang.org/p/0Cdic16edP
The Go Programming Language Specification
Numeric types
int32 the set of all signed 32-bit integers (-2147483648 to 2147483647)
int64 the set of all signed 64-bit integers (-9223372036854775808 to 9223372036854775807)
The value of an n-bit integer is n bits wide and represented using
two's complement arithmetic.
There is also a set of predeclared numeric types with
implementation-specific sizes:
uint either 32 or 64 bits
int same size as uint
To see the implementation-specific size of int, run this program.
package main
import (
"fmt"
"runtime"
"strconv"
)
func main() {
fmt.Println(
"For "+runtime.GOARCH+" the implementation-specific size of int is",
strconv.IntSize, "bits.",
)
}
Output:
For amd64 the implementation-specific size of int is 64 bits.
On Go Playground: http://play.golang.org/p/7O6dEdgDNd
For amd64p32 the implementation-specific size of int is 32 bits.

Related

int vs int32 return value

I am running into an issue, which seems to be related to int32 vs int data type. My program is returning different values on different environments.
For example, on go playground, I notice the value returned is -4 (which is expected value). But the same on Leetcode with same input returns a value of 4294967292. While it returned this value, when I print it, I get -4 (see output added later).
I tried casting to int32(res) but didn't help. Also didn't find any directly related in textbook. Please help me understand why this is different on go playground vs Leetcode.
https://play.golang.org/p/qXMd9frlhbe
package main
import (
"fmt"
)
func main() {
fmt.Printf("%v", singleNumber([]int{-2,-2,1,1,-3,1,-3,-3,-4,-2}))
}
func singleNumber(nums []int) int {
sum := make([]int, 32)
for _, v := range nums {
for i := 0; i < 32; i++ {
if sum[i] != 0 {
sum[i] += 1 & (v >> uint32(i))
} else {
sum[i] = 1 & (v >> uint32(i))
}
}
}
res := 0
for k, v := range sum {
if (v%3) != 0 {
res |= (v%3) << uint32(k)
}
}
fmt.Printf("res %+v\n", res)
return res
}
Same on Leetcode gives the output:
Input:
[-2,-2,1,1,-3,1,-3,-3,-4,-2]
Output:
4294967292
Expected:
-4
Stdout:
res -4
The textbook you are looking for is
The Go Programming Language Specification
Numeric types
A numeric type represents sets of integer or floating-point values.
The predeclared architecture-independent numeric types are:
uint32 set of all unsigned 32-bit integers (0 to 4294967295)
uint64 set of all unsigned 64-bit integers (0 to 18446744073709551615)
int32 set of all signed 32-bit integers (-2147483648 to 2147483647)
int64 set of all signed 64-bit integers (-9223372036854775808 to 9223372036854775807)
There is also a set of predeclared numeric types with
implementation-specific sizes:
uint either 32 or 64 bits
int same size as uint
Check the size of type int. On the Go Playground it's 4 bytes or 32 bits.
package main
import (
"fmt"
"runtime"
"unsafe"
)
func main() {
fmt.Println("arch", runtime.GOARCH)
fmt.Println("int", unsafe.Sizeof(int(0)))
}
Playground: https://play.golang.org/p/2A6ODvhb1Dx
Output (Playground):
arch amd64p32
int 4
Run the program in your (LeetCode) environment. It's likely 8 bytes or 64 bits.
For example, in my environment,
Output (Local):
arch amd64
int 8
Here are some fixes to your code,
package main
import (
"fmt"
"runtime"
)
func main() {
fmt.Println(runtime.GOARCH)
fmt.Printf("%v\n", singleNumber([]int{-2, -2, 1, 1, -3, 1, -3, -3, -4, -2}))
}
func singleNumber(nums []int) int {
sum := make([]int, 64)
for _, v := range nums {
for i := range sum {
sum[i] += 1 & (v >> uint(i))
}
}
res := 0
for k, v := range sum {
if (v % 3) != 0 {
res |= (v % 3) << uint(k)
}
}
fmt.Printf("res %+v\n", res)
return res
}
Playground: https://play.golang.org/p/kaoSuesu2Oj
Output (Playground):
amd64p32
res -4
-4
Output (Local):
amd64
res -4
-4

generate Random uint64 between min and max

How can I generate a random 64 bit unsigned integer in Go?
First I need to call
rand.Seed(0)
and then I need a function that returns a uint64 with the following signature
func random(min, max uint64) uint64 {
}
The function above should return a random 64 bit unsigned integer in the
range [min, max] (min and max included)
I'm not sure why you are being downvoted. I think you are worried about the case where max - min is greater than MaxInt64 in which case rand.Int63n would fail as you have remarked. I would handle that case separately.
const maxInt64 uint64 = 1 << 63 - 1
func random(min, max uint64) uint64 {
return randomHelper(max - min) + min
}
func randomHelper(n uint64) uint64 {
if n < maxInt64 {
return uint64(rand.Int63n(int64(n+1)))
}
x := rand.Uint64()
for x > n {
x = rand.Uint64()
}
return x
}

golang convert big.Float to big.Int

convert big.Float to big.Int, i write code below, but it overflow with uint64, so what's the correct way to cenvert big.Float to big.Int.
package main
import "fmt"
import "math/big"
func FloatToBigInt(val float64) *big.Int {
bigval := new(big.Float)
bigval.SetFloat64(val)
coin := new(big.Float)
coin.SetInt(big.NewInt(1000000000000000000))
bigval.Mul(bigval, coin)
result := new(big.Int)
f,_ := bigval.Uint64()
result.SetUint64(f)
return result
}
func main() {
fmt.Println("vim-go")
fmt.Println(FloatToBigInt(float64(10)))
fmt.Println(FloatToBigInt(float64(20)))
fmt.Println(FloatToBigInt(float64(30)))
fmt.Println(FloatToBigInt(float64(40)))
fmt.Println(FloatToBigInt(float64(50)))
fmt.Println(FloatToBigInt(float64(100)))
fmt.Println(FloatToBigInt(float64(1000)))
fmt.Println(FloatToBigInt(float64(10000)))
}
A big int bigger than uint64 will always cause an overflow as uint64 has fixed size. You should use the following method on *Float:
func (*Float) Int
The changes required would be:
func FloatToBigInt(val float64) *big.Int {
bigval := new(big.Float)
bigval.SetFloat64(val)
// Set precision if required.
// bigval.SetPrec(64)
coin := new(big.Float)
coin.SetInt(big.NewInt(1000000000000000000))
bigval.Mul(bigval, coin)
result := new(big.Int)
bigval.Int(result) // store converted number in result
return result
}
Working example: https://play.golang.org/p/sEhH6iPkrK
Use the function Float.Int(nil)
I have worked with a regular float64 number (not big.Float) and found out that conversion via string is the most precise way. Check it out
Note: the example is for float64 -> decimal(,20) conversion.
func bigIntViaString(flt float64) (b *big.Int) {
if math.IsNaN(flt) || math.IsInf(flt, 0) {
return nil // illegal case
}
var in = strconv.FormatFloat(flt, 'f', -1, 64)
const parts = 2
var ss = strings.SplitN(in, ".", parts)
// protect from numbers without period
if len(ss) != parts {
ss = append(ss, "0")
}
// protect from ".0" and "0." values
if ss[0] == "" {
ss[0] = "0"
}
if ss[1] == "" {
ss[1] = "0"
}
const (
base = 10
fraction = 20
)
// get fraction length
var fract = len(ss[1])
if fract > fraction {
ss[1], fract = ss[1][:fraction], fraction
}
in = strings.Join([]string{ss[0], ss[1]}, "")
// convert to big integer from the string
b, _ = big.NewInt(0).SetString(in, base)
if fract == fraction {
return // ready
}
// fract < 20, * (20 - fract)
var (
ten = big.NewInt(base)
exp = ten.Exp(ten, big.NewInt(fraction-int64(fract)), nil)
)
b = b.Mul(b, exp)
return
}
https://play.golang.org/p/_lkyQ_0udjd

Too many results in a loop for Project Euler #145

I am trying to create a solution for Project Euler #145. I am writing in Go. When I run my program I get a result of 125. The expected result is 120. I have 2 different ways I have tried to write the code but both come up with the same answer. Any help pointing out my error would be appreciated.
Code option #1 using strings:
package main
import (
"fmt"
"strconv"
)
//checks to see if all the digits in the number are odd
func is_Odd(sum int) bool {
intString := strconv.Itoa(sum)
for x := len(intString); x > 0; x-- {
newString := intString[x-1]
if newString%2 == 0 {
return false
}
}
return true
}
//reverse the number passed
func reverse_int(value int) int {
intString := strconv.Itoa(value)
newString := ""
for x := len(intString); x > 0; x-- {
newString += string(intString[x-1])
}
newInt, err := strconv.Atoi(newString)
if err != nil {
fmt.Println("Error converting string to int")
}
return newInt
}
//adds 2 int's passed to it and returns an int
func add(x int, y int) int {
return x + y
}
func main() {
//functions test code
/*y := 35
x := reverse_int(y)
z := add(x,y)
fmt.Println(is_Odd(z))*/
counter := 1
for i := 1; i < 1000; i++ {
flipped := reverse_int(i)
sum := add(flipped, i)
oddCheck := is_Odd(sum)
if oddCheck {
fmt.Println(counter, ":", i, "+", flipped, "=", sum)
counter++
}
}
counter--
fmt.Println("total = ", counter)
}
Code option #2 using only ints:
package main
import (
"fmt"
)
var counter int
//breaks down an int number by number and checks to see if
//all the numbers in the int are odd
func is_Odd(n int) bool {
for n > 0 {
remainder := n % 10
if remainder%2 == 0 {
return false
}
n /= 10
}
return true
}
//adds 2 int's passed to it and returns an int
func add(x int, y int) int {
return x + y
}
//reverses the int passed to it and returns an int
func reverse_int(n int) int {
var new_int int
for n > 0 {
remainder := n % 10
new_int *= 10
new_int += remainder
n /= 10
}
return new_int
}
func main() {
//functions test code
/*y := 35
x := reverse_int(y)
z := add(x,y)
fmt.Println(is_Odd(z))*/
counter = 1
for i := 1; i < 1000; i++ {
flipped := reverse_int(i)
sum := add(flipped, i)
oddCheck := is_Odd(sum)
if oddCheck {
//fmt.Println(counter,":",i,"+",flipped,"=",sum)
counter++
}
}
counter--
fmt.Println(counter)
}
Leading zeroes are not allowed in either n or reverse(n) so in reverse(n int) int remove Leading zeroes like so:
remainder := n % 10
if first {
if remainder == 0 {
return 0
}
first = false
}
try this:
package main
import (
"fmt"
)
//breaks down an int number by number and checks to see if
//all the numbers in the int are odd
func isOdd(n int) bool {
if n <= 0 {
return false
}
for n > 0 {
remainder := n % 10
if remainder%2 == 0 {
return false
}
n /= 10
}
return true
}
//adds 2 int's passed to it and returns an int
func add(x int, y int) int {
return x + y
}
//reverses the int passed to it and returns an int
func reverse(n int) int {
first := true
t := 0
for n > 0 {
remainder := n % 10
if first {
if remainder == 0 {
return 0
}
first = false
}
t *= 10
t += remainder
n /= 10
}
return t
}
func main() {
counter := 0
for i := 0; i < 1000; i++ {
flipped := reverse(i)
if flipped == 0 {
continue
}
sum := add(flipped, i)
if isOdd(sum) {
counter++
//fmt.Println(counter, ":", i, "+", flipped, "=", sum)
}
}
fmt.Println(counter)
}
output:
120
You're ignoring this part of the criteria:
Leading zeroes are not allowed in either n or reverse(n).
Five of the numbers you count as reversible end in 0. (That means their reverse has a leading zero.) Stop counting those as reversible and you're done.
Some positive integers n have the property that the sum [ n +
reverse(n) ] consists entirely of odd (decimal) digits. For instance,
36 + 63 = 99 and 409 + 904 = 1313. We will call such numbers
reversible; so 36, 63, 409, and 904 are reversible. Leading zeroes are
not allowed in either n or reverse(n).
All digits of the sum must all be odd.
Try this one: https://play.golang.org/p/aUlvKrb9SB

bytewise compare varint encoded int64's

I'm using levigo, the leveldb bindings for Go. My keys are int64's and need to be kept sorted. By default, leveldb uses a bytewise comparator so I'm trying to use varint encoding.
func i2b(x int64) []byte {
b := make([]byte, binary.MaxVarintLen64)
n := binary.PutVarint(b, x)
return key[:n]
}
My keys are not being sorted correctly. I wrote the following as a test.
var prev int64 = 0
for i := int64(1); i < 1e5; i++ {
if bytes.Compare(i2b(i), i2b(prev)) <= 0 {
log.Fatalf("bytewise: %d > %d", b2i(prev), i)
}
prev = i
}
output: bytewise: 127 > 128
playground
I'm not sure where the problem is. Am I doing the encoding wrong? Is varint not the right encoding to use?
EDIT:
BigEndian fixed width encoding is bytewise comparable
func i2b(x int64) []byte {
b := make([]byte, 8)
binary.BigEndian.PutUint64(b, uint64(x))
return b
}
The varint encoding is not bytewise comparable* wrt to the order of the values it caries. One option how to write the ordering/collating function (cmp bellow) is for example:
package main
import (
"encoding/binary"
"log"
)
func i2b(x int64) []byte {
var b [binary.MaxVarintLen64]byte
return b[:binary.PutVarint(b[:], x)]
}
func cmp(a, b []byte) int64 {
x, n := binary.Varint(a)
if n < 0 {
log.Fatal(n)
}
y, n := binary.Varint(b)
if n < 0 {
log.Fatal(n)
}
return x - y
}
func main() {
var prev int64 = 0
for i := int64(1); i < 1e5; i++ {
if cmp(i2b(i), i2b(prev)) <= 0 {
log.Fatal("fail")
}
prev = i
}
}
Playground
(*) The reason is (also) the bit fiddling performed.

Resources