Я пытаюсь создать калькулятор из двоичного в десятичный для Apple Watch, используя Swift 4.

Код, с которым у меня проблема, таков:

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
}

Я использую цикл while, чтобы получить индекс indexOfString и проверить, совпадает ли в строке reverse с конкретным индексом с "1".

Проблема в том, что я получаю сообщение об ошибке выполнения при выполнении оператора if.

Ошибка выглядит так:

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)

Итак, как я могу получить определенный символ String и сравнить его с другим символом, не получив этого сбоя?

0
Apostolos Pezodromou Apope 17 Дек 2017 в 16:31

1 ответ

Лучший ответ

Ваш подход к получению определенного символа из строки на самом деле правильный, в вашем коде есть еще две проблемы:

  • Индекс i должен работать до и исключая reverse.count. Это удобно сделать с помощью оператора «полуоткрытого диапазона» (..<).
  • ^ - это побитовый оператор xor, а не возведение в степень. Возведение в степень выполняется с помощью функции pow(), в вашем случае

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

    или с оператором "сдвиг влево" <<, если основание равно 2.

Так что это будет рабочий вариант:

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

Но вы можете просто перечислить символы строки в обратном порядке вместо индексации (что также более эффективно):

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

Еще проще с прямой итерацией, не требуется reversed() или <<:

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

Что предлагает использовать reduce():

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

Но зачем изобретать велосипед? Просто используйте init?(_:radix:) из стандартной библиотеки Swift (с бесплатная проверка ошибок):

let binaryString = "10010"
if let result = Int(binaryString, radix: 2) {
    print(result)
} else {
    print("invalid input")
}
4
Martin R 17 Дек 2017 в 15:53