如何将AnyBase转换为Base10?

时间:2018-02-10 20:00:00

标签: ios swift string encoding base

我发现some code要将 Base10-String 编码为自定义BaseString

func stringToCustomBase(encode: Int, alphabet: String) -> String {
    var base = alphabet.count, int = encode, result = ""
    repeat {
        let index = alphabet.index(alphabet.startIndex, offsetBy: (int % base))
        result = [alphabet[index]] + result
        int /= base
    } while (int > 0)
    return result
}

......用这句话来称呼它:

let encoded = stringToCustomBase(encode: 9291, alphabet: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
print(encoded)

上面的编码效果很好。但是如何解码编码的字符串?

因为我不知道如何将(在这种情况下为Base62 [alphabet.count = 62] )解码为人类可读的字符串(在本例中为[] Base10 ])任何帮助都会受到超级赞赏。

PS :(不需要完整的代码解决方案,我也可以提出某种pseudo-code或者只是few-lines of code

这是我到目前为止所尝试的:

func reVal(num: Int) -> Character {
    if (num >= 0 && num <= 9) {
        return Character("\(num)")
    }
    return Character("\(num - 10)A");
}


func convertBack() {
    var index = 0;
    let encoded = "w2RDn3"
    var decoded = [Character]()
    var inputNum = encoded.count
    repeat {
        index+=1
        decoded[index] = reVal(num: inputNum % 62)
        //encoded[index] = reVal(inputNum % 62);
        inputNum /= 62;

    }  while (inputNum > 0)
    print(decoded);
}

2 个答案:

答案 0 :(得分:1)

根据原始算法,您需要遍历编码字符串的每个字符,在字母表中找到该字符的位置,并计算新结果。

以下是方法和一些测试代码:

func stringToCustomBase(encode: Int, alphabet: String) -> String {
    var base = alphabet.count, string = encode, result = ""
    repeat {
        let index = alphabet.index(alphabet.startIndex, offsetBy: (string % base))
        result = [alphabet[index]] + result
        string /= base
    } while (string > 0)
    return result
}

func customBaseToInt(encoded: String, alphabet: String) -> Int? {
    let base = alphabet.count
    var result = 0
    for ch in encoded {
        if let index = alphabet.index(of: ch) {
            let mult = result.multipliedReportingOverflow(by: base)
            if (mult.overflow) {
                 return nil
            } else {
                let add = mult.partialValue.addingReportingOverflow(alphabet.distance(from: alphabet.startIndex, to: index))
                if (add.overflow) {
                    return nil
                } else {
                    result = add.partialValue
                }
            }
        } else {
            return nil
        }
    }

    return result
}


let startNum = 234567
let alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
let codedNum = stringToCustomBase(encode: startNum, alphabet: alphabet)
let origNun = customBaseToInt(encoded: codedNum, alphabet: alphabet)

我使customBaseToInt方法返回一个可选结果,以防编码值中的字符不在提供的字母表中。

答案 1 :(得分:0)

您可以通过reduce

实现此目的
enum RadixDecodingError: Error {
    case invalidCharacter
    case overflowed
}

func customRadixToInt(str: String, alphabet: String) throws -> Int {
    return try str.reduce(into: 0) {
        guard let digitIndex = alphabet.index(of: $1) else {
            throw RadixDecodingError.invalidCharacter
        }
        let multiplied = $0.multipliedReportingOverflow(by: alphabet.count)
        guard !multiplied.overflow else {
            throw RadixDecodingError.overflowed
        }
        let added = multiplied.partialValue.addingReportingOverflow(alphabet.distance(from: alphabet.startIndex, to: digitIndex))
        guard !added.overflow else {
            throw RadixDecodingError.overflowed
        }
        $0 = added.partialValue
    }
}

我使用异常抛出机制,以便调用者可以区分无效字符或溢出错误。