golang:对非常长的二进制位串表示的按位运算
golang: bitwise operation on very long binary bit string representation
作为练习,在输入中我得到了 2 个非常大的 string,其中包含长二进制表示,这里是短的,但可能超过 100 位:
示例
11100
00011
按位或输出(作为字符串)
11111
我的方法是解析每个字符串字符并进行按位或运算并构建一个新字符串,但是处理大条目太长而且效果不佳。
然后 ParseInt 方法被限制为 64 位长度
num1, err:= strconv.ParseInt("11100", 2, 64)
num2, err:= strconv.ParseInt("00011", 2, 64)
res := num1 | num2
如何处理 2 个字符串二进制表示之间的按位或?
您 可以 通过字符比较创建按位或字符串,或者您可以使用 math/big
执行任意大数值运算。这是此类操作的示例:
package main
import "fmt"
import "math/big"
func main() {
num1 := "11100"
num2 := "00011"
var bigNum1 big.Int
var bigNum2 big.Int
var result big.Int
if _, ok := bigNum1.SetString(num1, 2); !ok {
panic("invalid num1")
}
if _, ok := bigNum2.SetString(num2, 2); !ok {
panic("invalid num2")
}
result.Or(&bigNum1, &bigNum2)
for i := result.BitLen() - 1; i >= 0; i-- {
fmt.Print(result.Bit(i))
}
fmt.Println()
}
虽然您可以将它们转换为数字以执行按位运算,但如果您的唯一目标是对两个字符串执行单个按位或,将字符串解析为数字的效率将低于简单地迭代字符串以实现你的最终结果。仅当您对二进制形式的数字执行大量操作时,这样做才有意义。
对以下字符串执行 OR 运算的示例代码。请注意,此代码假定字符串的长度与问题中的示例相同,如果它们的长度不同,您也需要处理它。
package main
import "fmt"
func main() {
n1 := "1100"
n2 := "0011"
fmt.Printf("Input: %v | %v\n", n1, n2)
if len(n1) != len(n2) {
fmt.Println("Only supports strings of the same length")
return
}
result := make([]byte, len(n1))
for i := 0; i < len(n1); i++ {
switch n1[i] {
case '0':
switch n2[i] {
case '0':
result[i] = '0'
case '1':
result[i] = '1'
}
case '1':
switch n2[i] {
case '0':
result[i] = '1'
case '1':
result[i] = '1'
}
}
}
fmt.Println("Result: ", string(result))
}
这个怎么样:
package main
import "fmt"
func main(){
a := "01111100"
b := "1001000110"
var longest, len_diff int
if len(a) > len(b) {
longest = len(a)
len_diff = len(a) - len(b)
} else {
longest = len(b)
len_diff = len(b) - len(a)
}
temp_slice := make([] byte, longest)
var a_start, b_start int
if len(a) > len(b) {
for i := 0; i < len_diff; i++ {
temp_slice[i] = a[i]
}
a_start = len_diff
} else {
for i := 0; i < len_diff; i++ {
temp_slice[i] = b[i]
}
b_start = len_diff
}
for i := 0; i < (longest - len_diff); i++ {
if a[a_start + i] == '1' || b[b_start + i] == '1' {
temp_slice[len_diff + i] = '1'
} else {
temp_slice[len_diff + i] = '0'
}
}
fmt.Println(string(temp_slice))
}
备选方案:试试这个库:https://github.com/aristofanio/bitwiser。
您可以解析像位串这样的大字节数组。参见:
package main
import (
"github.com/aristofanio/bitwiser"
)
func main() {
//
b0, _ := bitwiser.ParseFromBits("011100")
b1, _ := bitwiser.ParseFromBits("11010011100")
//
println(b0.ToString()) //output: 0x1c (len(array) = 1byte)
println(b1.ToString()) //output: 0x069c (len(array) = 2bytes)
}
作为练习,在输入中我得到了 2 个非常大的 string,其中包含长二进制表示,这里是短的,但可能超过 100 位:
示例
11100
00011
按位或输出(作为字符串)
11111
我的方法是解析每个字符串字符并进行按位或运算并构建一个新字符串,但是处理大条目太长而且效果不佳。
然后 ParseInt 方法被限制为 64 位长度
num1, err:= strconv.ParseInt("11100", 2, 64)
num2, err:= strconv.ParseInt("00011", 2, 64)
res := num1 | num2
如何处理 2 个字符串二进制表示之间的按位或?
您 可以 通过字符比较创建按位或字符串,或者您可以使用 math/big
执行任意大数值运算。这是此类操作的示例:
package main
import "fmt"
import "math/big"
func main() {
num1 := "11100"
num2 := "00011"
var bigNum1 big.Int
var bigNum2 big.Int
var result big.Int
if _, ok := bigNum1.SetString(num1, 2); !ok {
panic("invalid num1")
}
if _, ok := bigNum2.SetString(num2, 2); !ok {
panic("invalid num2")
}
result.Or(&bigNum1, &bigNum2)
for i := result.BitLen() - 1; i >= 0; i-- {
fmt.Print(result.Bit(i))
}
fmt.Println()
}
虽然您可以将它们转换为数字以执行按位运算,但如果您的唯一目标是对两个字符串执行单个按位或,将字符串解析为数字的效率将低于简单地迭代字符串以实现你的最终结果。仅当您对二进制形式的数字执行大量操作时,这样做才有意义。
对以下字符串执行 OR 运算的示例代码。请注意,此代码假定字符串的长度与问题中的示例相同,如果它们的长度不同,您也需要处理它。
package main
import "fmt"
func main() {
n1 := "1100"
n2 := "0011"
fmt.Printf("Input: %v | %v\n", n1, n2)
if len(n1) != len(n2) {
fmt.Println("Only supports strings of the same length")
return
}
result := make([]byte, len(n1))
for i := 0; i < len(n1); i++ {
switch n1[i] {
case '0':
switch n2[i] {
case '0':
result[i] = '0'
case '1':
result[i] = '1'
}
case '1':
switch n2[i] {
case '0':
result[i] = '1'
case '1':
result[i] = '1'
}
}
}
fmt.Println("Result: ", string(result))
}
这个怎么样:
package main
import "fmt"
func main(){
a := "01111100"
b := "1001000110"
var longest, len_diff int
if len(a) > len(b) {
longest = len(a)
len_diff = len(a) - len(b)
} else {
longest = len(b)
len_diff = len(b) - len(a)
}
temp_slice := make([] byte, longest)
var a_start, b_start int
if len(a) > len(b) {
for i := 0; i < len_diff; i++ {
temp_slice[i] = a[i]
}
a_start = len_diff
} else {
for i := 0; i < len_diff; i++ {
temp_slice[i] = b[i]
}
b_start = len_diff
}
for i := 0; i < (longest - len_diff); i++ {
if a[a_start + i] == '1' || b[b_start + i] == '1' {
temp_slice[len_diff + i] = '1'
} else {
temp_slice[len_diff + i] = '0'
}
}
fmt.Println(string(temp_slice))
}
备选方案:试试这个库:https://github.com/aristofanio/bitwiser。 您可以解析像位串这样的大字节数组。参见:
package main
import (
"github.com/aristofanio/bitwiser"
)
func main() {
//
b0, _ := bitwiser.ParseFromBits("011100")
b1, _ := bitwiser.ParseFromBits("11010011100")
//
println(b0.ToString()) //output: 0x1c (len(array) = 1byte)
println(b1.ToString()) //output: 0x069c (len(array) = 2bytes)
}