0

I am trying to build a Binary to Decimal calculator for the Apple Watch using Swift 4.

The code I am having trouble is this:

var i = 0
var labelInputInt = 0
let labelOutputString = "10010" // Random number in binary 
let reverse = String(labelOutputString.reversed()) // Reversing the original string

while i <= reverse.count {
    let indexOfString = reverse.index(reverse.startIndex, offsetBy: i)

    if reverse[indexOfString] == "1" {
        labelInputInt += 2^i * 1
    }

    i += 1
}

I am using a while loop to get the index indexOfString and check if in the string reverse at the specific index it is equal with "1".

The problem is that I get a runtime error when the if statement is executed.

The error looks like this:

2  libpthread.so.0 0x00007fc22f163390
3  libswiftCore.so 0x00007fc22afa88a0 _T0s18_fatalErrorMessages5NeverOs12Stati
cStringV_A2E4fileSu4lines6UInt32V5flagstFTfq4nnddn_n + 96
4  libswiftCore.so 0x00007fc22afb3323
5  libswiftCore.so 0x00007fc22afdf9a2
6  libswiftCore.so 0x00007fc22aedca19 _T0SS9subscripts9CharacterVSS5IndexVcfg 
+ 9
7  libswiftCore.so 0x00007fc22f591294 _T0SS9subscripts9CharacterVSS5IndexVcfg 
+ 74139780
8  swift           0x0000000000f2925f
9  swift           0x0000000000f2d402
10 swift           0x00000000004bf516
11 swift           0x00000000004ae461
12 swift           0x00000000004aa411
13 swift           0x0000000000465424
14 libc.so.6       0x00007fc22d88d830 __libc_start_main + 240
15 swift           0x0000000000462ce9
Stack dump:
0.    Program arguments: /home/drkameleon/swift4/usr/bin/swift -frontend -inte
rpret tmp/XfwP0oM7FJ.swift -disable-objc-interop -suppress-warnings -module-na
me XfwP0oM7FJ 
Illegal instruction (core dumped)

So, how can I get a specific character of a String and compare it with another character without getting this crash?

0

1 Answer 1

4

Your approach to get a specific character from a string is actually correct, there are two other problems in your code:

  • The index i should run up to and excluding reverse.count. This is conveniently done with the "half-open range" operator (..<).
  • ^ is the bitwise-xor operator, not exponentiation. Exponentiation is done with the pow() function, in your case

    labelInputInt += Int(pow(2.0, Double(i)))
    

    or with the "shift-left" operator << if the base is 2.

So this would be a working variant:

for i in 0 ..< reverse.count {
    let indexOfString = reverse.index(reverse.startIndex, offsetBy: i)
    if reverse[indexOfString] == "1" {
        labelInputInt += 1 << i
    }
    i += 1
}

But you can simply enumerate the characters of a string in reverse order instead of subscripting (which is also more efficient):

let binaryString = "10010"
var result = 0
for (i, char) in binaryString.reversed().enumerated() {
    if char == "1" {
        result += 1 << i
    }
}
print(result)

Even simpler with forward iteration, no reversed() or << needed:

let binaryString = "10010"
var result = 0
for char in binaryString {
    result = 2 * result
    if char == "1" {
        result += 1
    }
}
print(result)

Which suggests to use reduce():

let binaryString = "10010"
let result = binaryString.reduce(0) { 2 * $0 + ($1 == "1" ? 1 : 0) }
print(result)

But why reinvent the wheel? Just use init?(_:radix:) from the Swift standard library (with error-checking for free):

let binaryString = "10010"
if let result = Int(binaryString, radix: 2) {
    print(result)
} else {
    print("invalid input")
}
Sign up to request clarification or add additional context in comments.

2 Comments

(1 << i) instead of Int(pow(2.0, Double(i))) perhaps?
@vacawama: You are completely right. I wanted to provide the "correct" version of exponentiation, both versions added now.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.