【问题标题】:How to replace this String operations with Bitwise operations?如何用按位操作替换此字符串操作?
【发布时间】:2019-01-29 20:00:33
【问题描述】:

考虑到我在 Base 对象中有这个字段:

//these fields have their bits constantly permuted
//and have their values defined to "011233455677..."
//to integers acts like Strings

var ul = 0x011233
var ur = 0x455677
var dl = 0x998bba
var dr = 0xddcffe

考虑到我有这种方法可以将这些字段作为字符串值操作:

private fun Cubo.isSolved(): Boolean {             
    val solved = Base()

    //function to append "leading zero" to the hex integer
    fun fill(s: String) = if (s.length == 5) "0$s" else s

    //all these fields are declared at the global escope

    //converted ul, ur, dl, dr from solved obj to hex string
    a1 = fill(Integer.toHexString(solved.ul))
    b1 = fill(Integer.toHexString(solved.ur))
    c1 = fill(Integer.toHexString(solved.dl))
    d1 = fill(Integer.toHexString(solved.dr))

    //concats the converteds ul and ur into a new one
    ab1 = a1 + b1
    //concats the converteds dl and dr into a new one
    cd1 = c1 + d1

    //do the same with fields of THIS object
    a2 = fill(Integer.toHexString(this.ul))
    b2 = fill(Integer.toHexString(this.ur))
    c2 = fill(Integer.toHexString(this.dl))
    d2 = fill(Integer.toHexString(this.dr))
    ab2 = a2 + b2
    cd2 = c2 + d2

    //checks if concatenated fields from THIS object exists inside the 
    //duplicated [solved] object fields.
    //This will help me to check if fields from THIS object are 
    //cyclic/circular permutations of the [solved] object.
    return (ab1 + ab1).contains(ab2) && (cd1 + cd1).contains(cd2)
}

一旦字段为整数,我的目标是知道如何用按位运算替换该运算?

我正在尝试这个,因为我的应用程序非常慢,并且这种方法在循环调用一千次后会降低其性能,然后意识到提高我的应用程序性能的一种方法可能是使用按位运算。

为了简化这个方法的思想,它只是用来验证字段 THIS 对象对应于“SOLVED”对象的字段,但这样做是考虑到测试对象的字段可能是循环排列。

【问题讨论】:

  • 您是否进行了分析以知道这需要很长时间?
  • 第一行的val solved = Base()是什么原因?换句话说,solved(及其字段)对于给定的运行实际上是一个常数吗?
  • @EpicPandaForce,当我在 Android 模拟器中运行它时,该方法的使用会增加 20~30 秒到迭代的最终时间。可以说我在 600000 次循环中运行此方法。
  • @SergGr solved var 只是为了获取原始值以与当前修改后的值进行比较。

标签: java string algorithm kotlin bitwise-operators


【解决方案1】:

连接

“连接”两个十六进制 6 位数字实际上是第一个数字的 24 位左移(因为每个十六进制数字有 4 位,长度为 6)并按位取第二个数字 or 的结果转变。

infix fun Long.hexConcat(num: Long) = num.or(shl(24))

包含

要检查 6 位十六进制数是否包含在 12 位十六进制数的前 6 位或后 6 位中,您可以按位 and 两者(测试结束)。要测试它是否在开头,您必须先将其右移 24 位,然后按位 and 它。

infix fun Long.containsAsHex(num: Long) = and(num) == num || shr(24) == num

示例:

fun main() {

    val a = 0x011233L
    val b = 0x455677L

    val c = a hexConcat b

    println(c.toString(16)) // 11233455677
    println(c containsAsHex a) // true
}

当然,您可以进一步参数化 hexConcat 以不将其限制为 6 位十六进制数字。


如果 6 位十六进制数可以在 12 位十六进制数中的任何位置:

要检查一个十六进制数是否“包含”另一个十六进制数,请将其向右移动 4 位,直到其值为 0,或者您找到匹配项,这意味着按位移动的数字 and 要测试的数字必须等于要测试的数字。

infix fun Long.containsAsHex(num: Long): Boolean {

    var shifted = this

    while (true) {

        if(shifted.and(num) == num) {
            return true
        }

        if(shifted == 0L) {
            return false
        }

        shifted = shifted.shr(4) // shift one hex digit
    }

    @Suppress("UNREACHABLE_CODE")
    return false
}

【讨论】:

  • 我喜欢你的方法,但没有奏效。一个试过:val kk = 0x011233L hexConcat 0x455677L println(kk containsAsHex 0x455677L),然后得到一个错误的结果。重要的是要知道0x011233L0x455677L 连接应该导致“011233455677”,并且正如我们所见,“序列”455677 存在于连接值中。
  • @LucasSousa 我的错!转换必须在循环结束时完成!修复它:)
  • @LucasSousa 在特殊情况下仅检查所讨论的数字是前 6 位还是后 6 位,您可以完全简单地包含十六进制。看我的编辑。更通用的解决方案如下。
  • 您的方法有效,但开头的前导零存在问题。我想你必须知道urul 字段的延续,那么,在类的操作中,它的十六进制值可以被置换。例如,如果我们测试 ul112334 和你的 556770"(两者都顺时针旋转 1 位),我们会得到 false 结果。无论如何,正如@SergGr 指出的那样,我创建了一个关于这个问题的更详细的问题。看一看:question.
【解决方案2】:

假设您的目标状态是固定的并且具有 12 个十六进制字符的固定大小,我会做一些不同的事情。我首先预先计算了solved 的所有旋转,然后使用简单的等号检查它们。我不确定将其存储在您的应用程序中的何处有意义。在这段代码中,我将其作为target 参数传递。

class Cubo() {

    var ul: Int = 0x011233
    var ur: Int = 0x455677
    var dl: Int = 0x998bba
    var dr: Int = 0xddcffe

    constructor(ul: Int, ur: Int, dl: Int, dr: Int) : this() {
        this.ul = ul
        this.ur = ur
        this.dl = dl
        this.dr = dr
    }

    fun isSolved(target: TargetState): Boolean {
        return target.checkSolved(this)
    }
}


class TargetState(val uRot: AllRotations, val dRot: AllRotations) {
    constructor(c: Cubo) : this(AllRotations(concat(c.ul, c.ur)), AllRotations(concat(c.dl, c.dr))) {
    }

    fun checkSolved(c: Cubo): Boolean {
        val u = concat(c.ul, c.ur)
        val d = concat(c.dl, c.dr)
        return uRot.contains(u) and dRot.contains(d)
    }

    companion object {
        fun concat(l: Int, r: Int): Long {
            return l.toLong().shl(AllRotations.singleBitsCount).or(r.toLong())
        }

    }
}


class AllRotations(value: Long) {

    val rotatedValues = Array<Long>(doubleDigitsCount) { i -> rotate(value, digitSize * i) }

    fun contains(test: Long): Boolean {
        for (v in rotatedValues) {
            if (v == test)
                return true
        }
        return false
    }


    companion object {
        const val singleDigitsCount = 6
        const val doubleDigitsCount = 2 * singleDigitsCount
        const val digitSize = 4
        const val singleBitsCount = digitSize * singleDigitsCount
        const val doubleBitsCount = digitSize * doubleDigitsCount
        const val mask = 1L.shl(doubleBitsCount) - 1


        fun rotate(value: Long, shift: Int): Long {
            val hi = value.shl(shift).and(mask)
            val lo = value.shr(doubleBitsCount - shift)
            return hi.or(lo)
        }
    }
}

这是一个简单的测试:

val solved = Cubo(0x011233, 0x455677, 0, 0)
val targetState = TargetState(solved)

val c1 = Cubo(0x233455, 0x677011, 0, 0)
val c2 = Cubo(0x455677, 0x011233, 0, 0)
val cbad = Cubo(0x455677, 0x011233, 1, 0)

println(c1.isSolved(targetState))
println(c2.isSolved(targetState))
println(cbad.isSolved(targetState))

【讨论】:

  • 完美解决方案!与我的 String 方法相比,您如何看待它的优化?
  • @LucasSousa,我怀疑它会更快,但很可能不会快很多。坦率地说,我相信你应该向我们展示你真正的高级问题,这样我们就可以首先讨论一些算法级的改进,而不是一些低级的优化。这些优化可能会有所帮助,但通常您可以通过使用好的算法获得更多收益。
  • 当然。那我会用更多关于我在做什么的信息来更新我的问题。好吗?
  • 我认为最好为此创建一个新问题。这个已经用于你的低级东西了
  • 好吧,我刚刚创建了它here
猜你喜欢
  • 2021-09-26
  • 1970-01-01
  • 2013-05-04
  • 1970-01-01
  • 2020-06-08
  • 2010-09-10
  • 1970-01-01
  • 1970-01-01
  • 2021-07-17
相关资源
最近更新 更多