Search code examples
swifthexoctal

How to convert a fractional Octal to Hex fraction and vice versa in Swift 3?


I am looking for a way to convert a fractional Octal to Hex fraction and vice versa in Swift 3. Self written code without third-party library and Foundation. For example this code converts Octal Integer to Hex:

for num in OctalVal {     
            switch num {
            case "0": result = result * 8
            case "1": result = result * 8 + 1
            case "2": result = result * 8 + 2
            case "3": result = result * 8 + 3
            case "4": result = result * 8 + 4
            case "5": result = result * 8 + 5
            case "6": result = result * 8 + 6
            case "7": result = result * 8 + 7
            default: return "Error"    
            } 
        }
        n2 = result
        while n2 > 0 {
            c2 = n2 % 16
            n2 = n2 / 16
            k2.append("\(c2)")
        }

        for i in k2.reversed() {
            if(i == "10"){
                fs2 += "A"
            }
            else if(i == "11") {
                fs2 += "B"
            }
            else if(i == "12") {
                fs2 += "C"
            }
            else if(i == "13") {
                fs2 += "D"
            }
            else if(i == "14") {
                fs2 += "E"
            }
            else if(i == "15") {
                fs2 += "F"
            }
            else {
                fs2 += "\(i)"
            }  
        }   
        return "\(fs2)"  
    }

And this one Hex to Octal:

for num in Left {
            switch num {
            case "0": result += "0000"
            break;
            case "1": result += "0001"
            break;
            case "2": result += "0010"
            break;
            case "3": result += "0011"
            break;
            case "4": result += "0100"
            break;
            case "5": result += "0101"
            break;
            case "6": result += "0110"
            break;
            case "7": result += "0111"
            break;
            case "8": result += "1000"
            break;
            case "9": result += "1001"
            break;
            case "A": result += "1010"
            break;
            case "B": result += "1011"
            break;
            case "C": result += "1100"
            break;
            case "D": result += "1101"
            break;
            case "E": result += "1110"
            break;
            case "F": result += "1111"
            break;
            default: return "Error"
            }
        }

For example: 12D.3AF9F to 455.1657476 (Octal)

Any ideas regarding fractional part? Thank you for your attention to my request


Solution

  • Convert hex to binary, pad to make binary string a multiple of 3 in length, then convert binary to octal:

    func hexadecimalFractToOctal(_ hex: String) -> String {
        let hexToBin = ["0": "0000", "1": "0001", "2": "0010", "3": "0011",
                        "4": "0100", "5": "0101", "6": "0110", "7": "0111",
                        "8": "1000", "9": "1001", "A": "1010", "B": "1011",
                        "C": "1100", "D": "1101", "E": "1110", "F": "1111"]
    
        let binToOct = ["000": "0", "001": "1", "010": "2", "011": "3",
                        "100": "4", "101": "5", "110": "6", "111": "7"]
    
        // Convert hex string to binary
        var bin = ""
        for char in hex.characters {
            bin += hexToBin[String(char)] ?? ""
        }
    
        // Pad the string to a multiple of 3 binary digits
        bin += ["", "00", "0"][bin.characters.count % 3]
    
        var binChars = bin.characters
    
        var oct = ""
    
        // Convert binary string to octal 3 digits at a time
        while binChars.count > 0 {
            let b = String(binChars.prefix(3))
            binChars = binChars.dropFirst(3)
            oct += binToOct[b] ?? ""
        }
    
        return oct
    }
    
    print(hexadecimalFractToOctal("3AF9F"))  // "1657476"
    

    And the other direction (octal -> hexadecimal):

    func octalFractToHexadecimal(_ oct: String) -> String {
        let octToBin = ["0": "000", "1": "001", "2": "010", "3": "011",
                        "4": "100", "5": "101", "6": "110", "7": "111"]
    
        let binToHex = ["0000": "0", "0001": "1", "0010": "2", "0011": "3",
                        "0100": "4", "0101": "5", "0110": "6", "0111": "7",
                        "1000": "8", "1001": "9", "1010": "A", "1011": "B",
                        "1100": "C", "1101": "D", "1110": "E", "1111": "F"]
    
        // Convert octal string to binary
        var bin = ""
        for char in oct.characters {
            bin += octToBin[String(char)] ?? ""
        }
    
        // Pad the string to a multiple of 4 binary digits
        bin += ["", "000", "00", "0"][bin.characters.count % 4]
    
        var binChars = bin.characters
    
        var hex = ""
    
        // Convert binary string to hexadecimal 4 digits at a time
        while binChars.count > 0 {
            let b = String(binChars.prefix(4))
            binChars = binChars.dropFirst(4)
            hex += binToHex[b] ?? ""
        }
    
        return hex
    }
    
    print(octalFractToHexadecimal("1657476")) // "3AF9F0"