ошибка malloc при генерации огромного случайного числа

Я хочу получить случайный элемент от 0 до огромного числа (2 ^ 31).

Я попытался создать Array из такого Range (чтобы я мог использовать Swift Array.randomElement), как это сделано здесь< /а>:

let myArray: [Int64] = [Int64](0...4294967292)

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

MyPoject(1569,0x100cc2f40) malloc: не удается выделить область mach_vm_map(size=34359738368) не удалось (код ошибки=3) MyProject(1569,0x100cc2f40) malloc: установить точку останова в malloc_error_break для отладки

Конечно, я могу написать пользовательскую функцию для создания массива, но это пахнет, особенно потому, что массив каждый раз будет одинаковым.

Предоставляет ли Swift лучшее решение?


person Daniel Springer    schedule 09.12.2018    source источник
comment
Для такого массива потребуется около 32 ГБ памяти — сколько у вас вычислительных ресурсов?   -  person Martin R    schedule 09.12.2018
comment
Что вы хотите сделать с массивом, чего нельзя сделать с помощью Range?   -  person Sweeper    schedule 09.12.2018
comment
@DaniSpringer: Действительно. – Вы должны рассказать нам о своей настоящей проблеме.   -  person Martin R    schedule 09.12.2018
comment
ClosedRange также имеет метод randomElement.   -  person Sweeper    schedule 09.12.2018
comment
Вы рассматривали возможность использования константы Int64.max вместо уродливого магического значения?   -  person Sulthan    schedule 09.12.2018
comment
Я позволил себе откатить последнее редактирование — оно удалило контекст существующих ответов, сделав их неясными для будущих читателей этого вопроса и ответа.   -  person Martin R    schedule 09.12.2018
comment
@MartinR согласился, спасибо. Я пытался уменьшить шум. :)   -  person Daniel Springer    schedule 09.12.2018


Ответы (2)


Сообщение об ошибке

malloc: невозможно выделить область mach_vm_map (размер = 34359738368)

сообщает, что среда выполнения не может выделить 32 ГБ памяти — это то, что потребовалось бы для массива из 4294967292 64-битных целых чисел.

let myArray: [Int64] = [Int64](0...4294967292)

Но нет необходимости создавать массив для этой цели. Начиная с Swift 4.2 вы можете просто позвонить

let rnd = Int64.random(in: 0...4294967292)
// or
let rnd = Int64.random(in: 0..<4294967293)

с помощью одного из

static func random(in range: ClosedRange<Self>) -> Self
static func random(in range: Range<Self>) -> Self

методы протокола FixedWidthInteger.

Наконец, обратите внимание, что 4294967292 не 2^31 = 2147483648 — если намерение состоит в том, чтобы создать случайное число в диапазоне от 0 (включительно) до 2^31 (исключительно), тогда

let rnd = Int32.random(in: 0...Int32.max)

бы на хитрость.

person Martin R    schedule 09.12.2018
comment
Имеет ли смысл добавлять к вопросу объяснение ошибки памяти, поскольку, возможно, такой вопрос может возникнуть, даже зная значение этой ошибки? - person Daniel Springer; 09.12.2018
comment
@DaniSpringer: Мне не совсем понятно, что вы предлагаете, но объяснения должны быть в ответах, а не в вопросах. Однако вы можете изменить заголовок на "Ошибка malloc при создании огромного случайного числа", чтобы отличить его от других вопросов о случайных числах и облегчить поиск тем, у кого есть похожая проблема. - person Martin R; 09.12.2018
comment
Если вам нужны неповторяющиеся случайные значения от 0 до 2^31, это более сложная проблема. Мой обычный подход к построению массива всех возможных значений и удалению одного случайного значения за раз до тех пор, пока у вас не будет желаемого количества значений, не будет работать, потому что для этого требуется слишком много памяти, как обнаружил ОП. Вам нужно будет добавлять случайные значения в набор, пока у вас не будет желаемого количества записей, а затем преобразовать набор в массив. - person Duncan C; 09.12.2018

ClosedRange также имеет метод randomElement в Swift 4.2:

print((0...4294967292).randomElement()!)

Обратите внимание, что вы сказали, что вам нужно случайное число от 0 до 2 ^ 31, но вы использовали 1...4294967292 вместо 0...4294967292 в своем примере.

person Sweeper    schedule 09.12.2018
comment
Ах, это так, это хорошо знать. И вау, ТАК ты сделал это менее чем за 20 минут ???? Да, правда в том, что 0 и 1 оба хороши (вот почему я не осознавал, что был непоследовательным), потому что моя идея заключалась в том, что я могу добавить 1 к результату позже. - person Daniel Springer; 09.12.2018