Adding/subtracting two numeric strings - go

I have two variables with big numbers set as strings:
var numA = "340282366920938463463374607431768211456"
var numB = "17014118346046923173168730371588410572"
I want to be able to add and subtract these kinds of large string numbers in Go.
I know I need to use math/big but I still can not for the life of me figure out how, so any example help will be greatly appreciated!

You may use big.NewInt() to create a new big.Int value initialized with an int64 value. It returns you a pointer (*big.Int). Alternatively you could simply use the builtin new() function to allocate a big.Int value which will be 0 like this: new(big.Int), or since big.Int is a struct type, a simple composite literal would also do: &big.Int{}.
Once you have a value, you may use Int.SetString() to parse and set a number given as string. You can pass the base of the string number, and it also returns you a bool value indicating if parsing succeeded.
Then you may use Int.Add() and Int.Sub() to calculate the sum and difference of 2 big.Int numbers. Note that Add() and Sub() write the result into the receiver whose method you call, so if you need the numbers (operands) unchanged, use another big.Int value to calculate and store the result.
See this example:
numA := "340282366920938463463374607431768211456"
numB := "17014118346046923173168730371588410572"
ba, bb := big.NewInt(0), big.NewInt(0)
if _, ok := ba.SetString(numA, 10); !ok {
panic("invalid numA")
}
if _, ok := bb.SetString(numB, 10); !ok {
panic("invalid numB")
}
sum := big.NewInt(0).Add(ba, bb)
fmt.Println("a + b =", sum)
diff := big.NewInt(0).Sub(ba, bb)
fmt.Println("a - b =", diff)
Output (try it on the Go Playground):
a + b = 357296485266985386636543337803356622028
a - b = 323268248574891540290205877060179800884

Related

Working with bitstrings and big.Int in Go

I'm new to Go and I'm working on a few exercises to get up to speed. How can I convert a string representing a sequence of bits to the appropriate datatype in Go?
For eg, I see that if its a bitstring representing a 64-bit number, I can do :-
val, err := strconv.ParseInt(bitstring, 2, 64)
However, if the bitstring represents a larger number(say 1024 or 2048 bits), how can I go about converting that number to the appropriate type in Go? I believe the type for managing big integers in Go is big.Int.
Yes, you may use the big.Int type, and its Int.SetString() method, passing 2 as the base.
Example:
i := big.NewInt(0)
if _, ok := i.SetString("10101010101010101010101010101010101010101010101010101010101010101010101010", 2); !ok {
fmt.Println("Invalid number!")
} else {
fmt.Println(i)
}
Output (try it on the Go playground):
12592977287652387236522

Slice merge in golang recommendation

Is there a way to make this golang code shorter?
func MergeSlices(s1 []float32, s2 []int32) []int {
var slice []int
for i := range s1 {
slice = append(slice, int(s1[i]))
}
for i := range s2 {
slice = append(slice, int(s2[i]))
}
return slice
}
You can't eliminate the loops to convert each element to int individually, because you can't convert whole slices of different element types. For explanation, see this question: Type converting slices of interfaces in go
The most you can do is use named result type, and a for range with 2 iteration values, where you can omit the first (the index) by assigning it to the blank identifier, and the 2nd will be the value:
func MergeSlices(s1 []float32, s2 []int32) (s []int) {
for _, v := range s1 {
s = append(s, int(v))
}
for _, v := range s2 {
s = append(s, int(v))
}
return
}
But know that your code is fine as-is. My code is not something to always follow, it was to answer your question: how to make your code shorter. If you want to improve your code, you could start by looking at its performance, or even refactoring your code to not end up needing to merge slices of different types.
Your code should be correct, maintainable, readable, and reasonably efficient. Note that shortness of code is not one of the important goals. For good reason, Stack Exchange has another site for Code Golf questions: Programming Puzzles & Code Golf.
Your code could be improved; it's inefficient. For example, merging two len(256) slices,
BenchmarkMergeSlices 200000 8350 ns/op 8184 B/op 10 allocs/op
Here's a more efficient (and longer) version:
BenchmarkMergeSlices 300000 4420 ns/op 4096 B/op 1 allocs/op
.
func MergeSlices(s1 []float32, s2 []int32) []int {
slice := make([]int, 0, len(s1)+len(s2))
for i := range s1 {
slice = append(slice, int(s1[i]))
}
for i := range s2 {
slice = append(slice, int(s2[i]))
}
return slice
}
Use the Go Code Review Comments for Named Result Parameters. For example: "Don't name result parameters just to avoid declaring a var inside the function; that trades off a minor implementation brevity at the cost of unnecessary API verbosity. Clarity of docs is always more important than saving a line or two in your function."
var s1 []int
var s2 []int
newSlice = append(s1, s2...)
The code can't get any shorter, but that's a goal of dubious value to begin with; it's not overly verbose as-is. You can, however, likely improve performance by eliminating the intermediate allocations. Every time you call append, if the target slice doesn't have enough space, it expands it, guessing at the necessary size since you haven't told it how much space it will need.
The simplest would just be to presize your target slice (replace var slice []int with slice := make([]int, 0, len(s1) + len(s2)); that way the appends never have to expand it. Setting the second parameter to 0 is important, that sets the length to zero, and the capacity to the total size needed, so that your appends will work as expected.
Once you've presized it though, you can get rid of the appends entirely, and directly set each index:
func MergeSlices(s1 []float32, s2 []int32) []int {
slice := make([]int, len(s1) + len(s2))
for i,v := range s1 {
slice[i] = int(v)
}
for i,v := range s2 {
slice[i+len(s1)] = int(v)
}
return slice
}
Playground link

How to count number of bytes in an integer

I have the following variables:
var foo int8
var bar [5]int8
I want to count number of bytes in both variables and output the sum - so right here it should be 1 + 5 = 6. Is this possible?
You can use reflect.Size, this returns a uintptr for some reason, but is actually just the exact same thing as unsafe.SizeOf without having to use unsafe.
var x [8]byte
t := reflect.TypeOf(x)
fmt.Println(t.Size())
The snags are going to be maps, slices, strings, and pointers, which you'll get the size of the header/metadata (or just the pointer size for pointers). If that's okay, great! If not, you can handle this in various ways, this is the best I have off the top of my head:
func UnderlyingSize(x interface{}) uintptr {
v := reflect.ValueOf(x)
t := v.Type()
var size uintptr;
switch t.Kind() {
// For the builtin collections, we just multiply the len by the
// element size, for maps also do the key
case reflect.Map:
l := uintptr(v.Len())
size = t.Key().Size()*l + t.Elem().Size()*l
case reflect.Slice:
t := t.Elem();
size = t.Size() * uintptr(v.Len())
case reflect.Ptr:
t := t.Elem();
size = t.Size()
// Strings are just byte arrays, so it's just the len
case reflect.String:
size = uintptr(v.Len())
// For an interface, we need to find the underlying type
case reflect.Interface:
v := v.Elem()
size = UnderlyingSize(v)
// For anything else, including arrays, Size returns the correct value
default:
size = t.Size();
}
return size
}
There is an argument to be made for using Cap rather than Len, but it's easy enough to change yourself. You can also add t.Size() to any of these values if you want the size of the header information AND the underlying size. Note a word of warning that the real map probably takes more memory than just the key+value+header size, since there's probably some extra information under the hood.
If you have a data structure that's a collection, you'll have to implement something like this yourself, but if it's a simple struct (i.e. only made of POD structs and builtin types), you can simply add up UnderlyingSize of all the members.
You can use unsafe.Sizeof (https://play.golang.org/p/FroasKud7I):
unsafe.Sizeof(foo) + unsafe.Sizeof(bar)

iterating over over a 2D slice in go

I am taking the "Tour of Go", and had a question regarding the Exercise: Slices example. Currently I can create the picture by iterating over each index using the the [] operator, just like you could in C.
func Pic(dx, dy int) [][]uint8 {
pic := make([][]uint8, dy)
for i := range pic {
pic[i] = make([]uint8, dx)
for j := range pic[i] {
pic[i][j] = uint8(1)
}
}
return pic
}
However, when I try to do something like below, I get an panic: runtime error: index out of range error. I tried adding print statements and calling Pic(3, 3), which printed out a 3x3 array just fine.
func Pic(dx, dy int) [][]uint8 {
pic := make([][]uint8, dy)
for _, y := range pic {
y = make([]uint8, dx)
for _, x := range y {
x = uint8(1)
_ = x // x has to be used
//fmt.Print("1")
}
//fmt.Print("\n")
}
return pic
}
Any thoughts on what I am doing wrong?
The main problem is your attempt to do assignment. Check my example using your code; https://play.golang.org/p/lwoe79jQ70
What you actually get out of the latter implementation is a 3x0 array, all of the inner arrays are empty. The reason for this is because you're using the range variable for assignment which doesn't work. If the current index is 0, y != pic[0], pic[0] is assigned to y however, y is temporary storage, it typically is the same address and is over written on each iteration. So after the latter example executes, all your x direction arrays are empty, indexing into one causes a panic.
Basically you should just be using your first implementation because it works fine and is the way you would typically do this. But the take away is, when you do a, b := range Something b != Something[a], it is it's on instance, it goes out of scope at the bottom of the loop and assigning to it will not cause a state change to the collection Something, instead you must assign to Something[a] if you want to modify Something[a].
range copies the values from the slice you're iterating over.
See: http://golang.org/ref/spec#RangeClause
To clarify what happens see this simple code example and its output:
package main
import "fmt"
func main() {
s := "hi"
//s[0] = 'H' // cannot assign to s[0]
for _, v := range s {
fmt.Printf("%T, %[1]v, %X\n", v, &v)
v = 'H' // has no effect: this is local var not ref
}
fmt.Println(s)
}
The output is:
int32, 104, C0820042D4
int32, 105, C0820042D4
hi
As you see the address of variable v is not changing (C0820042D4) and v is local variable and range copies value to it, so changing v has no effect.
Here v is rune (int32 alias), A rune is an integer value identifying a Unicode code point, and you cannot assign to s[0] and this won’t compile: s[0] = 'H'
so v = 'H' has no effect on s, it is just local variable.

Misunderstanding the usage of := in Go

I was reading this doc and saw the following fragment:
The := syntax is shorthand for declaring and initializing a variable, e.g. for var f string = "short" in this case.
f := "short"
fmt.Println(f)
The point is: is it only for strings? Or is it dymanic enough to understand what datatype should it store?
And plus: isn't it the same of var f = "short"?
Of course it infers the obvious type(s) returned by the expression on the right side.
The specification gives those examples :
i, j := 0, 10
f := func() int { return 7 }
ch := make(chan int)
r, w := os.Pipe(fd) // os.Pipe() returns two values
_, y, _ := coord(p) // coord() returns three values; only interested in y coordinate
Note that it's not dynamic : everything happens at compile time, the type(s) being given by the right part expression.

Resources