Почему следующий код разбился на iPhone 5, но не на iPhone 5S?

func rand(max: Int?) -> Int {
    var index = Int(arc4random())
    return max? != nil ? (index % max!) : index
}

Я получаю исключение в последней строке: EXC_BAD_INSTRUCTION

Я предполагаю, что это связано с тем, что iPhone 5S - 64-битный, а 5 - нет, но я не вижу ничего в вышеприведенной функции, которая имеет дело с 64 битами?

Изменить

Мне удалось решить проблему со следующими настройками, но я все еще не могу объяснить, почему.

func rand(max: Int?) -> Int {
    var index = arc4random()
    return max? != nil ? Int(index % UInt32(max!)) : Int(index)
}

Ответ 1

Integer тип Int - это 32-разрядное целое число на iPhone 5 и 64-разрядное целое число на 5S. Поскольку arc4random() возвращает a UInt32, который имеет двойной положительный диапазон Int на iPhone 5, ваша первая версия в основном имеет 50% -ный шанс сбой в этой строке:

var index = Int(arc4random())

Ваша измененная версия ждет конвертировать до тех пор, пока вы не возьмете сумму по модулю с помощью max, поэтому ее можно конвертировать в Int. Вы должны проверить arc4random_uniform, который обрабатывает модуль для вас и избегает некоторого смещения, присущего вашей текущей реализации.

Ответ 2

Как вам кажется, вы обнаружили, что arc4random возвращает целое число без знака 32 бит. Таким образом, от 0 до 4 294 967 295. Кроме того, Int - это другой размер в зависимости от системы, в которой он работает.

Из "Свифт-ссылка:"

On a 32-bit platform, Int is the same size as Int32.
On a 64-bit platform, Int is the same size as Int64.

На iPhone 5 Int будет удерживать только -2,147,483,648 до +2,147,483,647. На iPhone 5S Int может хранить -9,223,372,036,854,775,808 до +9,223,372,036,854,775,807. Целочисленное 32-битное целое число может переполнять Int32, но не Int64.

Дополнительная информация о том, какую функцию использовать и почему.