Создать массив одинарных поплавков из двойных поплавков в lisp?

Когда я пытаюсь создать такой массив с одним числом с плавающей запятой, я получаю:

(make-array 2 :element-type 'single-float :initial-contents #(3.0 4.0))

, я получаю следующую ошибку:

The value 3.0 is not of type SINGLE-FLOAT

Есть ли способ создать массив с одним числом с плавающей запятой из простого вектора с двойным числом с плавающей запятой?


person Xaving    schedule 27.02.2015    source источник


Ответы (2)


Когда я пытаюсь создать такой массив с одним числом с плавающей запятой, я получаю:

(make-array 2 :element-type 'double-float :initial-contents #(3.0 4.0))

Вы пытаетесь создать массив single-float (что говорит ваш текст) или массив double-float (как предлагает код)? Чтобы создать массив двойных чисел с плавающей запятой, используйте (make-array :element-type 'double-float ), а для создания массива single-float, вы должны использовать (make-array :element-type 'single-float ). Однако в любом случае элементы в аргументе initial-elements должны соответствовать указанному типу; запись HyperSpec для make-array Говорит, что:

Initial-contents состоит из вложенной структуры последовательностей. Количество уровней в структуре должно равняться рангу массива. Каждый лист вложенной структуры должен иметь тип, заданный element-type.

Поскольку одинарное число с плавающей запятой и двойное число с плавающей запятой не являются одним и тем же типом, вам необходимо заранее преобразовать данные. Вы можете использовать map для создания результата или map-into, если вы хотите сначала создать его, а затем скопировать результаты. Например:

CL-USER> (map '(vector double-float *)
         #'(lambda (x) (float x 1.0d0))
         #(3.0 4.0))
#(3.0d0 4.0d0)

CL-USER> (map-into (make-array 2 :element-type 'double-float)
                   #'(lambda (x) (float x 1.0d0))
                   #(3.0 4.0))
#(3.0d0 4.0d0)

Those examples assume that you're trying to create an array of double-floats, which is what your code suggests. If you just want an array of single-floats, then you can just the correct type:

CL-USER> (make-array 2 :element-type 'single-float :initial-contents #(3.0 4.0))
#(3.0 4.0)

Или, как заметил Сванте, вы можете просто написать #(3.0 4.0) или #(3.0s0 4.0s0) напрямую.

person Joshua Taylor    schedule 27.02.2015
comment
Большое спасибо. Я адаптирую ваш ответ для одиночного поплавка, и он работает. - person Xaving; 27.02.2015
comment
@ Xaving, что ты имеешь в виду, адаптируй это? В вопросе, который вы спросили, как создать вектор двойных поплавков из вектора одинарных поплавков. Вот что делает этот код... - person Joshua Taylor; 27.02.2015
comment
— спросил я наоборот. Итак, в вашем решении все, что связано с двойным, я заменил его одинарным поплавком. - person Xaving; 27.02.2015
comment
@Xaving Я рад, что ответ помогает. Я вижу, что в вашем тексте предлагается создать массив с одинарным числом с плавающей запятой, но ваш код предполагает, что вы пытались создать массив типа с двойным числом с плавающей запятой, поскольку вы используете :element-type double-float. - person Joshua Taylor; 27.02.2015
comment
@Xaving Но теперь проблема просто исчезает, верно? Так как (make-array 2 :element-type 'single-float :initial-contents #(3.0 4.0)) успешно возвращает #(3.0 4.0) (по крайней мере, если *read-default-float-format* имеет одиночное число с плавающей запятой). - person Joshua Taylor; 27.02.2015
comment
На самом деле, в моей среде sbcl #(3.0 4.0) считается двойным числом с плавающей запятой. Спасибо, что указали на использование формата read-default-float-format. - person Xaving; 28.02.2015

Вы можете напрямую использовать вектор одиночных поплавков:

#(3.0s0 4.0s0)

Для двойных поплавков используйте:

#(3.0d0 4.0d0)

Тип поплавка для чтения по умолчанию задается *read-default-float-format*. См. Главу 2.3.2.2 CLHS (Синтаксис Float).

Редактировать: это означает, что следующее делает то, что вам нужно:

(make-array 2 :element-type 'single-float :initial-contents #(3.0s0 4.0s0))

Если в вашем коде много таких выражений, может оказаться целесообразным привязать *read-default-float-format* глобально перед загрузкой затронутых исходных файлов.

person Svante    schedule 27.02.2015
comment
Это обеспечивает вектор одиночных чисел с плавающей запятой, но тип не будет специализирован для одиночных чисел с плавающей запятой. - person Joshua Taylor; 27.02.2015
comment
@JoshuaTaylor: да, но это не имеет значения для :initial-contents. Я, возможно, должен быть более ясным об этом. - person Svante; 28.02.2015
comment
имеет ли смысл LET? Может ли это повлиять на чтение поплавков в форме, которую он заключает? - person Rainer Joswig; 28.02.2015
comment
@RainerJoswig: О да, вы должны убедиться в этом во время чтения, так что это не нравится. Извиняюсь! - person Svante; 28.02.2015