Dealing with Octal Numbers in Swift

Dealing with Octal numbers in swift

Using string conversion functions is pretty horrible in my option. How about something like this instead:

func octalToDecimal(var octal: Int) -> Int {
var decimal = 0, i = 0
while octal != 0 {
var remainder = octal % 10
octal /= 10
decimal += remainder * Int(pow(8, Double(i++)))
}
return decimal
}

var decimal = octalToDecimal(777) // decimal is 511

How to convert from Octal to Decimal in Swift

From Octal to Decimal

There is a specific Int initializer for this

let octal = 10
if let decimal = Int(String(octal), radix: 8) {
print(decimal) // 8
}

From Decimal to Octal

let decimal = 8
if let octal = Int(String(decimal, radix: 8)) {
print(octal) // 10
}

Note 1: Please pay attention: parenthesis are different in the 2 code snippets.

Note 2: Int initializer can fail for string representations of number with more exotic radixes. Please read the comment by @AMomchilov below.

Only allowing octal numbers

I would replace all the scanf and harcoded functions with fgets and strtol:

enum {oct = 8, dec = 10, hex = 16};

int to_number(int base, bool *match)
{
char str[32];
long num = 0;

*match = false;
if (fgets(str, sizeof str, stdin))
{
char *ptr;

num = strtol(str, &ptr, base);
*match = (*ptr == '\n'); // match is true if strtol stops scanning
// at the newline left by fgets
}
return (int)num;
}

...

bool match;
int num = to_number(oct, &match);

printf("%d %s an octal\n", num, match ? "is" : "is not");

EDIT:

As pointed out by @klutt in comments, since strtol returns a long, ideally the function should also return long in order to avoid the cast, then, if you really need an int, you can cast the return of the function:

long to_number(int base, bool *match);

int num = (int)to_number(oct, &match);

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

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"

Octal Numbering System

Easy. Just continue the pattern from the left side of the dot:

1*8^1 + 0*8^0 + 3*8^-1 + 4*8^-2 = 8.4375


Related Topics



Leave a reply



Submit