Swift native functions to have numbers as hex strings
IosMacosSwiftNumbersHexIos Problem Overview
Is there any native Swift way for any (at least integer) number to get its hexadecimal representation in a string? And the inverse. It must not use Foundation. For example the String class has a function
func toInt() -> Int?
which converts a string representing an integer to its Int value. I am looking for something similar, using the hex strings. I know this is easily implementable, but if Swift has it there already it would be better. Otherwise if you made already an extension of String and Int to achieve the following:
let anHex = "0xA0"
if let anInt = anHex.toInt() {
println(anInt) // prints 128
println(anInt.toHexString()) // prints "0xA0"
}
I know it isn't rocket science but in case please share it.
PS: This is similar to this question, the difference is that it was very related to the Foundation framework, while I am not using it in my code (nor I am importing anything else) and for now I'd like to keep it in this way, also for learning purposes.
Ios Solutions
Solution 1 - Ios
As of Swift 2, all integer types have a constructor
init?(_ text: String, radix: Int = default)
so that both integer to hex string and hex string to integer conversions can be done with built-in methods. Example:
let num = 1000
let str = String(num, radix: 16)
print(str) // "3e8"
if let num2 = Int(str, radix: 16) {
print(num2) // 1000
}
(Old answer for Swift 1:) The conversion from an integer to a hex string can be done with
let hex = String(num, radix: 16)
(see for example https://stackoverflow.com/questions/26181221/how-to-convert-a-decimal-number-to-binary-in-swift). This does not require the import of any Framework and works with any base between 2 and 36.
The conversion from a hex string to an integer can be done with the BSD
library function strtoul()
(compare https://stackoverflow.com/questions/26790660/how-to-convert-a-binary-to-decimal-in-swift) if you are willing to import Darwin
.
Otherwise there is (as far as I know) no built-in Swift method. Here is an extension that converts a string to a number according to a given base:
extension UInt {
init?(_ string: String, radix: UInt) {
let digits = "0123456789abcdefghijklmnopqrstuvwxyz"
var result = UInt(0)
for digit in string.lowercaseString {
if let range = digits.rangeOfString(String(digit)) {
let val = UInt(distance(digits.startIndex, range.startIndex))
if val >= radix {
return nil
}
result = result * radix + val
} else {
return nil
}
}
self = result
}
}
Example:
let hexString = "A0"
if let num = UInt(hexString, radix: 16) {
println(num)
} else {
println("invalid input")
}
Solution 2 - Ios
update: Xcode 12.5 • Swift 5.4
extension StringProtocol {
func dropping<S: StringProtocol>(prefix: S) -> SubSequence { hasPrefix(prefix) ? dropFirst(prefix.count) : self[...] }
var hexaToDecimal: Int { Int(dropping(prefix: "0x"), radix: 16) ?? 0 }
var hexaToBinary: String { .init(hexaToDecimal, radix: 2) }
var decimalToHexa: String { .init(Int(self) ?? 0, radix: 16) }
var decimalToBinary: String { .init(Int(self) ?? 0, radix: 2) }
var binaryToDecimal: Int { Int(dropping(prefix: "0b"), radix: 2) ?? 0 }
var binaryToHexa: String { .init(binaryToDecimal, radix: 16) }
}
extension BinaryInteger {
var binary: String { .init(self, radix: 2) }
var hexa: String { .init(self, radix: 16) }
}
Testing:
print("7fffffffffffffff".hexaToDecimal) // "9223372036854775807" decimal integer
print("0x7fffffffffffffff".hexaToDecimal) // "9223372036854775807" decimal integer
print("7fffffffffffffff".hexaToBinary) // "111111111111111111111111111111111111111111111111111111111111111" binary (String)
print("0x7fffffffffffffff".hexaToBinary) // "111111111111111111111111111111111111111111111111111111111111111"
print("255".decimalToHexa) // "ff" hexa (String)
print("255".decimalToBinary) // "11111111" binary (String)
0b11111111
print("11111111".binaryToHexa) // "ff" hexa (String)
print("0b11111111".binaryToHexa) // "ff" hexa (String)
print("11111111".binaryToDecimal) // 255 decimal (Int)
print("0b11111111".binaryToDecimal) // 255 decimal (Int)
print(255.binary) // "11111111" binary (String)
print(255.hexa) // "ff" hexa (String)
Solution 3 - Ios
Swift 3:
String
to UInt
:
let str = "fcd7d7"
let number = UInt(str, radix: 16)!
print(number)
result: 16570327
UInt
to hex String
:
let number = UInt(exactly: 16570327)!
let str = String(number, radix: 16, uppercase: false)
print(str)
result: fcd7d7
Solution 4 - Ios
For Float, If you might want IEEE754 floating point to HEX
extension Float {
func floatToHex()->String {
return String(self.bitPattern, radix: 16, uppercase: true)
}
}
let f:Float = 3.685746e+19
let hex = f.floatToHex()
print("\(hex)")//5FFFC000
Or Visa-versa
extension String {
func hexToFloat() -> Float {
var toInt = Int32(truncatingBitPattern: strtol(self, nil, 16))
var toInt = Int32(_truncatingBits: strtoul(self, nil, 16)) //For Swift 5
var float:Float32!
memcpy(&float, &toInt, MemoryLayout.size(ofValue: float))
return float
}
}