stringtranslate.com

Нарезка массива

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

Типичными примерами среза массива являются извлечение подстроки из строки символов, « элл » в «привет о », извлечение строки или столбца из двумерного массива или извлечение вектора из матрицы .

В зависимости от языка программирования срез массива может состоять из непоследовательных элементов. Также, в зависимости от языка, элементы нового массива могут иметь псевдонимы (т. е. совместно использовать память) с элементами исходного массива.

Подробности

Для «одномерных» (одноиндексированных) массивов — векторов, последовательностей, строк и т. д. — наиболее распространенной операцией нарезки является извлечение нуля или более последовательных элементов. Таким образом, если у нас есть вектор, содержащий элементы (2, 5, 7, 3, 8, 6, 4, 1), и мы хотим создать срез массива с 3-го по 6-й элементы, мы получим (7, 3, 8, 6). В языках программирования , использующих схему индексации с отсчетом от 0, срез будет иметь индекс от 2 до 5 .

Сокращение диапазона любого индекса до одного значения фактически устраняет этот индекс. Эту функцию можно использовать, например, для извлечения одномерных срезов (векторов: в 3D, строк, столбцов и трубок [1] ) или двумерных срезов (прямоугольных матриц) из трехмерного массива. Однако, поскольку диапазон может быть указан во время выполнения, языки с проверкой типов могут потребовать явную нотацию (во время компиляции), чтобы фактически исключить тривиальные индексы.

Общее разделение массива может быть реализовано (независимо от того, встроено оно в язык или нет) путем ссылки на каждый массив через вектор или дескриптор  — запись, содержащую адрес первого элемента массива, а затем диапазон каждого индекса и соответствующий коэффициент в формула индексации. Этот метод также позволяет немедленно транспонировать массив , переворачивать индексы, выполнять подвыборку и т. д. Для таких языков, как C , где индексы всегда начинаются с нуля, вектор допинга массива с d индексами имеет как минимум 1 + 2 d параметров. Для языков, которые допускают произвольные нижние границы индексов, таких как Pascal , вектору соответствия требуется 1 + 3 d записей.

If the array abstraction does not support true negative indices (as for example the arrays of Ada and Pascal do), then negative indices for the bounds of the slice for a given dimension are sometimes used to specify an offset from the end of the array in that dimension. In 1-based schemes, -1 generally would indicate the second-to-last item, while in a 0-based system, it would mean the very last item.

History

The concept of slicing was surely known even before the invention of compilers. Slicing as a language feature probably started with FORTRAN (1957), more as a consequence of non-existent type and range checking than by design. The concept was also alluded to in the preliminary report for the IAL (ALGOL 58) in that the syntax allowed one or more indices of an array element (or, for that matter, of a procedure call) to be omitted when used as an actual parameter.

Kenneth Iverson's APL (1957) had very flexible multi-dimensional array slicing, which contributed much to the language's expressive power and popularity.

ALGOL 68 (1968) introduced comprehensive multi-dimension array slicing and trimming features.

Array slicing facilities have been incorporated in several modern languages, such as Ada 2005, Cobra, D, Fortran 90, Go, Rust, Julia, MATLAB, Perl, Python, S-Lang, Windows PowerShell and the mathematical/statistical languages GNU Octave, S and R.

Timeline of slicing in various programming languages

1964: PL/I

PL/I provides two facilities for array slicing.

DECLARE X(5,5); DECLARE Y(5) DEFINED(X(1SUB,1SUB));

A reference to Y(2) is a reference to X(2,2), and so on.

DECLARE X(5,5); X(*,1)=0;

1966: Фортран 66

Программисты на Фортране 66 могли воспользоваться преимуществом разрезания матриц только по строкам, и то только при передаче этой строки в подпрограмму :

  ПОДПРОГРАММА PRINT V ( VEC , LEN ) REAL VEC ( * ) PRINT * , ( VEC ( I ), I = 1 , LEN ) END                 ГЛАВНЫЙ ПАРАМЕТР ПРОГРАММЫ ( LEN = 3 ) РЕАЛЬНАЯ МАТРИЦА ( LEN , LEN ) МАТРИЦА ДАННЫХ / 1 , 1 , 1 , 2 , 4 , 8 , 3 , 9 , 27 / CALL PRINT V ( MATRIX ( 1 , 2 ), LEN ) КОНЕЦ                           

Результат:

 2,000000 4,000000 8,000000

Обратите внимание, что в FORTRAN 66 нет вектора привязки , поэтому длина среза также должна быть передана в качестве аргумента (или каким-либо другим способом) в функцию SUBROUTINE. В 1970-х годах у Паскаля и Си были аналогичные ограничения.

1968: Алгол 68

Итоговый отчет Algol68 содержит ранний пример нарезки, срезы указаны в форме:

[нижняя граница: верхняя граница] ¢ для компьютеров с расширенными наборами символов ¢

или:

(НИЖНЯЯ ГРАНИЦА..ВЕРХНЯЯ ГРАНИЦА) # ДЛЯ КОМПЬЮТЕРОВ ТОЛЬКО С 6-БИТНЫМИ СИМВОЛАМИ. #

Обе границы являются инклюзивными и могут быть опущены, и в этом случае они по умолчанию будут соответствовать объявленным границам массива. Ни возможность шага, ни псевдонимы диагональных срезов не являются частью пересмотренного отчета.

Примеры:

[3, 3]real a := ((1, 1, 1), (2, 4, 8), (3, 9, 27)); # объявление переменной матрицы #
[,]real c = ((1, 1, 1), (2, 4, 8), (3, 9, 27)); # постоянная матрица, размер подразумевается #
ref[]реальная строка:= a[2,]; # псевдоним/ ссылка на фрагмент строки #
ref[]real col2 = a[, 2]; # постоянный псевдоним/ ссылка на второй столбец #
print ((a[:, 2], новая строка)); # фрагмент второго столбца #
print ((a[1⌈a, :], новая строка)); # фрагмент последней строки #
print ((a[:, 2⌈a], новая строка)); # фрагмент последнего столбца #
print ((a[:2, :2], новая строка)); # ведущий "срез" подматрицы 2х2 #
+1,0000 10 +0 +4,0000 10 +0 +9,0000 10 +0+3,0000 10 +0 +9,0000 10 +0 +2,7000 10 +1+1,0000 10 +0 +8,0000 10 +0 +2,7000 10 +1+1,0000 10 +0 +1,0000 10 +0 +2,0000 10 +0 +4,0000 10 +0

1968: БАЗОВЫЙ

Системы HP 2000 , представленные в ноябре 1968 года, использовали HP Time-Shared BASIC в качестве основного интерфейса и языка программирования. Эта версия BASIC использовала нарезку для большинства операций по манипуляции со строками. Одной из странностей языка было то, что он допускал взаимозаменяемые круглые и квадратные скобки, и то, что использовалось на практике, обычно было функцией используемого компьютерного терминала .

Пример:

10 A$ = «ПРИВЕТ, МИР» 20 PRINT A$ ( 1 , 5 ) 30 PRINT A$ [ 7 , 11 ]     

Будет производить:

ПРИВЕТМИР

Системы HP широко использовались в начале 1970-х годов, особенно в технических школах и во многих небольших промышленных и научных учреждениях. [3] Когда в середине 1970-х годов появились первые микрокомпьютеры , HP также часто использовался в качестве образца для их диалектов BASIC. Яркие примеры включают Apple BASIC 1977 года , Atari BASIC 1978 года и Sinclair BASIC 1979 года . Этот стиль манипуляции обычно дает преимущества с точки зрения использования памяти и часто выбирается в системах с небольшим объемом памяти. Только диалект Синклера существенно отличался: TOвместо списка, разделенного запятыми, использовалось ключевое слово:

10 LET a$ = "ABCDE" ( от 2 до 4 ) 20 PRINT a$      

Срезирование также было выбрано в качестве основы для стандарта ANSI Full BASIC , в котором в качестве разделителя используется двоеточие и, таким образом, проводится различие между срезом и доступом к массиву:

10 DIM A$ ( 5 ) 20 LET A$ ( 2 ) = "ПРИВЕТ, МИР" 30 PRINT A$ ( 2 )( 1 : 5 )      

Хотя этот стиль доступа давал ряд преимуществ, особенно для небольших машин того времени, где-то после 1970 года компания Digital Equipment Corporation представила свой собственный вариант BASIC, который использовал функции LEFT$, RIGHT$и MID$string. Microsoft BASIC был написан на PDP-10 , и его BASIC использовался в качестве образца. В конце 1970-х годов оба стиля широко использовались, но к началу 1980-х годов функции в стиле DEC стали фактическим стандартом.

1970-е: МАТЛАБ

>  A  =  round ( rand ( 3 ,  4 ,  5 ) * 10 )  % трехмерный или кубический массив 3x4x5 >  A (:,  :,  3 )  % двумерный массив 3x4 по первому и второму измерениямответ  = 8  3  5  7  8  9  1  4  4  4  2  5>  A (:,  2 : 3 ,  3 )  % двумерный массив 3x2 по первому и второму измерениямответ  = 3  5  9  1  4  2>  A ( 2 : end ,  :,  3 )  % двумерный массив 2x4 с использованием ключевого слова 'end'; работает с GNU Octave 3.2.4ответ  = 6  1  4  6  10  1  3  1>  A ( 1 ,  :,  3 )  % одномерный массив по второму измерениюответ  = 8  3  5  7>  A ( 1 ,  2 ,  3 )  % одного значения ans  =  3

1976: С / Р

Массивы в S и GNU R всегда начинаются с единицы, поэтому индексы нового среза начинаются с единицы для каждого измерения, независимо от предыдущих индексов. Размеры с длиной, равной единице, будут отброшены (если drop = FALSE). Имена измерений (если они есть) будут сохранены.

> A <- array ( 1 : 60 , dim = c ( 3 , 4 , 5 )) # трехмерный или кубический массив 3x4x5 > A [, , 3 ] # двумерный массив 3x4 по первому и второму измерениям  [, 1 ] [, 2] [, 3] [, 4] [1,] 25 28 31 34 [2,] 26 29 32 35 [3,] 27 30 33 36 > A [, 2 : 3 , 3 , drop = FALSE ] # Подмножество кубического массива 3x2x1 (сохраненные размеры) , , 1                  [, 1] [, 2] [1,] 28 31 [2,] 29 32 [3,] 30 33 > A [, 2 , 3 ] # одномерный массив по первому измерению [1] 28 29 30 > A [ 1 , 2 , 3 ] # одно значение [1] 28      

1977: Фортран 77

В стандарте Fortran 77 появилась возможность разрезать и объединять строки:

ПРОГРАММА ГЛАВНАЯ ПЕЧАТЬ * , 'ABCDE' ( 2 : 4 ) КОНЕЦ   

Производит:

двоично-десятичный код

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

ПОДПРОГРАММА PRINT S ( STR ) CHARACTER * ( * ) STR PRINT * , STR END     ПРОГРАММА ГЛАВНЫЙ ВЫЗОВ ПЕЧАТЬ S ( 'ABCDE' ( 2 : 4 )) КОНЕЦ 

Опять производит:

двоично-десятичный код

1983: Ада 83 и выше

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

с  Text_IO ; процедура  Main  — это  Text  :  String  :=  «ABCDE» ; начать  Text_IO . Put_Line  ( Текст  ( 2..4  )  ) ; конец  основного ;

Производит:

двоично-десятичный код

Примечание. Поскольку индексы в Ada основаны на n, этот термин Text (2 .. 4)приведет к массиву с базовым индексом 2.

Определение для Text_IO.Put_Lineэтого:

пакет  Ada.Text_IO   процедура  Put_Line ( пункт  : в  строке );

Определение для Stringэтого:

пакет  Стандарт  подтип  Положительным  является  Целочисленный  диапазон  1  ..  Integer ' Last ; тип  String  — это  массив ( положительный  диапазон <  > )  символов  ; пакет прагмы ( строка );  

Поскольку Ада поддерживает истинно отрицательные индексы, type History_Data_Array is array (-6000 .. 2010) of History_Data;она не придает никакого особого значения отрицательным индексам. В приведенном выше примере термин Some_History_Data (-30 .. 30)будет разделен на период History_Dataс 31 г. до н.э. по 30 г. н.э. (поскольку нулевого года не было, номер года 0 фактически относится к 1 г. до н.э. ).

1987: Перл

Если мы имеем

= ( 2 , 5 , 7 , 3 , 8 , 6 , 4 );        

как указано выше, тогда первые 3 элемента, средние 3 элемента и последние 3 элемента будут:

[ 0 .. 2 ]; # (2, 5, 7) @a [ 2 .. 4 ]; # (7, 3, 8) @a [ - 3 ..- 1 ]; # (8, 6, 4)   

Perl поддерживает индексы отрицательных списков. Индекс -1 — это последний элемент, -2 — предпоследний элемент и т. д. Кроме того, Perl поддерживает нарезку на основе выражений, например:

[ 3 .. $#а ]; # 4-й элемент до конца (3, 8, 6, 4) @a [ grep { ! ( $_ % 3 ) } ( 0 ... $#a ) ]; # 1-й, 4-й и 7-й элементы (2,3,4) @a [ grep { ! (( $_ + 1 ) % 3 ) } ( 0 .. $#a ) ]; # каждый третий элемент (7,6)                      

1991: Питон

Если у вас есть следующий список:

>>> числа  =  [ 1 ,  3 ,  5 ,  7 ,  8 ,  13 ,  20 ]

Тогда можно выполнить срез, используя обозначение, аналогичное поиску элементов:

>>> nums [ 3 ]  # без нарезки 7 >>> nums [: 3 ]  # от индекса 0 (включительно) до индекса 3 (не включая) [1, 3, 5] >>> nums [ 1 : 5 ] [3 , 5, 7, 8] >>> цифры [ - 3 :] [8, 13, 20]

Обратите внимание, что Python допускает отрицательные индексы списков. Индекс -1 представляет последний элемент, -2 - предпоследний элемент и т. д. Python также позволяет использовать свойство шага, добавляя дополнительное двоеточие и значение. Например:

>>> nums [ 3 :] [7, 8, 13, 20] >>> nums [ 3 ::]  # == nums[3:] [7, 8, 13, 20] >>> nums [:: 3 ]  # начиная с индекса 0 и получая каждый третий элемент [1, 7, 20] >>> nums [ 1 : 5 : 2 ]  # от индекса 1 до индекса 5 и получая каждый второй элемент [3, 7]

Синтаксис шага ( nums[1:5:2]) был введен во второй половине 1990-х годов в результате запросов, выдвинутых научными пользователями Python «matrix-SIG» (группа специальных интересов). [4]

Семантика среза потенциально различается для каждого объекта; новая семантика может быть введена при перегрузке оператора индексации. В стандартных списках Python (которые представляют собой динамические массивы ) каждый фрагмент является копией. Срезы массивов NumPy , напротив, представляют собой представления одного и того же базового буфера.

1992: Фортран 90 и выше

В Фортране 90 срезы задаются в форме

нижняя_ граница : верхняя_ граница [: шаг ]

Обе границы являются инклюзивными и могут быть опущены, и в этом случае они по умолчанию будут соответствовать объявленным границам массива. По умолчанию Stride равен 1. Пример:

реальный , размерность ( м , п ) :: а ! объявление матричного вывода * , a (:, 2 ) ! второй столбец напечатайте * , a ( m , :) ! последнюю строку напечатайте * , a (: 10 , : 10 ) ! ведущая подматрица 10 на 10                 

1994: Analytica

Каждое измерение значения массива в Analytica идентифицируется индексной переменной. При нарезке или индексации синтаксис идентифицирует измерения, по которым вы нарезаете или индексируете, путем присвоения имени измерению. Такой как:

Индекс I := 1..5 {Определение числового индекса }Индекс J := ['A', 'B', 'C'] {Определение текстового индекса }Переменная X := Array(I, J, [[10, 20, 30], [1, 2, 3], ....]) { Определение двумерного значения }X[I = 1, J = 'B'] -> 20 { Индекс для получения единственного значения }X[I = 1] -> Array(J, [10, 20, 30]) { Вырезаем одномерный массив. }X[J = 2] -> Array(I, [20, 2, ....]) { Вырезаем одномерный массив по другому измерению. }X[I = 1..3] {Вырезаем первые четыре элемента над I, причем все элементы лежат над J}

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

1998: S-Lang

Нарезка массива была представлена ​​в версии 1.0. Более ранние версии не поддерживали эту функцию.

Предположим, что A представляет собой одномерный массив, такой как

 A = [1:50]; % А = [1, 2, 3, ...49, 50]

Затем массив B из первых 5 элементов A может быть создан с помощью

 Б = А[[:4]];

Аналогично, B может быть присвоен массиву из последних 5 элементов A с помощью:

 Б = А[[-5:]];

Другие примеры одномерной нарезки включают в себя:

 A[-1] % Последний элемент A A[*] % Все элементы A A[[::2]] % Все четные элементы A A[[1::2]] % Все нечетные элементы A A[[-1::-2]] % Все четные элементы в обратном порядке A[[[0:3], [10:14]]] % элементов 0–3 и 10–14

Нарезка многомерных массивов работает аналогично:

 A[-1, *] % Последняя строка A A[[1:5], [2:7]] % 2d массив, используя строки 1–5 и столбцы 2–7 A[[5:1:-1], [2:7]] % То же, что и выше, за исключением того, что строки перевернуты.

Индексы массива также могут быть массивами целых чисел. Например, предположим, что I = [0:9]это массив из 10 целых чисел. Тогда A[I]эквивалентно массиву из первых 10 элементов A. Практическим примером этого является операция сортировки, такая как:

 I = array_sort (a); % Получить список индексов сортировки Б = А[Я]; % B — это отсортированная версия A C = A[array_sort(A)]; % То же, что и выше, но более кратко.

1999: d

Рассмотрим массив:

int [] а = [ 2 , 5 , 7 , 3 , 8 , 6 , 4 , 1 ];          

Убери от этого:

int [] b = а [ 2 .. 5 ];     

и содержимое bбудет [7, 3, 8]. Первый индекс среза является инклюзивным, второй — исключающим.

авто c = а [$ -4 .. $ - 2 ] ;         

означает, что динамический массив cтеперь содержит [8, 6], поскольку внутри [] $символ относится к длине массива.

Срезы массива D имеют псевдонимы исходного массива, поэтому:

б [ 2 ] знак равно 10 ;  

означает, что aтеперь у него есть содержимое [2, 5, 7, 3, 10, 6, 4, 1]. Чтобы создать копию данных массива, а не только псевдоним, выполните:

авто б = а [ 2 .. 5 ]. дуп ;     

В отличие от Python, границы среза D не насыщаются, поэтому код, эквивалентный этому коду Python, является ошибкой в ​​D:

>>> d  =  [ 10 ,  20 ,  30 ] >>> d [ 1  :  5 ] [20, 30]

2004: SuperCollider

Язык программирования SuperCollider реализует некоторые концепции из J / APL . Нарезка выглядит следующим образом:

a  =  [ 3 ,  1 ,  5 ,  7 ]  // присваиваем массив переменной a a [ 0 .. 1 ]  // возвращаем первые два элемента a a [.. 1 ]  // возвращаем первые два элемента a: ноль можно опустить a [ 2 ..]  // возвращаем элемент от 3 до последнего a [[ 0 ,  3 ]]  // возвращаем первый и четвертый элементы aa [[ 0 ,  3 ]]  =  [ 100 ,  200 ]  // заменяем первый и четвертый элементы a a [ 2 ..]  =  [ 100 ,  200 ]  // заменяем два последних элемента a// присваиваем переменной a a  =  [[ 0 ,  1 ,  2 ,  3 ,  4 ],  [ 5 ,  6 ,  7 ,  8 ,  9 ],  [ 10 ,  11 ,  12 ,  13 ,  14 ],  [ 15 ,  16 ,  17 ,  18 ,  19 ]];  а . кусочек ( 2 ,  3 );  // берем фрагмент с координатами 2 и 3 (возвращает 13) a . срез ( ноль ,  3 );  // берем ортогональный срез (возвращает [3, 8, 13, 18])

2005: рыба

Массивы в fish всегда начинаются с единицы, поэтому индексы нового среза будут начинаться с единицы , независимо от предыдущих индексов.

>  set A ( seq 3  2 11 )  # $A — массив со значениями 3, 5, 7, 9, 11 >  echo  $A [( seq 2 )]  # Выведите первые два элемента $A 3 5 >  set B $A [ 1 2 ]  # $B содержит первый и второй элемент $A, т.е. 3, 5 >  установить -e A [ $B ] ;  echo  $A  # Сотрите третий и пятый элементы $A, выведите $A 3  5 9

2006: Кобра

Cobra поддерживает нарезку в стиле Python. Если у вас есть список

числа  =  [ 1 ,  3 ,  5 ,  7 ,  8 ,  13 ,  20 ]

тогда первые 3 элемента, средние 3 элемента и последние 3 элемента будут:

nums [: 3 ]  # равно [1, 3, 5] nums [ 2 : 5 ]  # равно [5, 7, 8] nums [ - 3 :]  # равно [8, 13, 20]

Cobra также поддерживает синтаксис в стиле срезов для «числовых циклов for»:

for  i  in  2  :  5  print  i # печатает 2, 3, 4для  j  в  3  print  j # выводит 0, 1, 2

2006: Windows PowerShell

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

PS> $a  =  2 ,  5 ,  7 ,  3 ,  8 ,  6 ,  4 ,  1 PS> # Выведите первые два элемента $a: PS> Write-Host  -NoNewline  $a [ 0 ,  1 ] 2 5 PS> # Вырезаем его с помощью оператора диапазона: PS> Write-Host  -NoNewline  $a [ 2 .. 5 ] 7 3 8 6 PS> # Получаем последние 3 элемента: PS> Write-Host  -NoNewline  $a [ - 3 ..- 1 ] 6 4 1 PS> # Возвращаем содержимое массива в обратном порядке: PS> Write-Host  -NoNewline  $a [( $a . Длина  -  1 .. 0 ]  # Длина — свойство из System.Object[] 1 4 6 8 3 7 5 2

2009: Вперёд

Go поддерживает синтаксис в стиле Python для нарезки (за исключением того, что отрицательные индексы не поддерживаются). Массивы и срезы можно нарезать. Если у вас есть ломтик

nums := []int{1, 3, 5, 7, 8, 13, 20}

then the first 3 elements, middle 3 elements, last 3 elements, and a copy of the entire slice would be:

nums[:3] // equals []int{1, 3, 5}nums[2:5] // equals []int{5, 7, 8}nums[4:] // equals []int{8, 13, 20}nums[:] // equals []int{1, 3, 5, 7, 8, 13, 20}

Slices in Go are reference types, which means that different slices may refer to the same underlying array.

2010: Cilk Plus

Cilk Plus supports syntax for array slicing as an extension to C and C++.

array_base [lower_bound:length[:stride]]*

Cilk Plus slicing looks as follows:

A[:] // All of vector AB[2:6] // Elements 2 to 7 of vector BC[:][5] // Column 5 of matrix CD[0:3:2] // Elements 0, 2, 4 of vector D

Cilk Plus's array slicing differs from Fortran's in two ways:

2012: Julia

Julia array slicing is like that of MATLAB, but uses square brackets. Example:

julia> x = rand(4, 3)4x3 Array{Float64,2}: 0.323877 0.186253 0.600605 0.404664 0.894781 0.0955007 0.223562 0.18859 0.120011 0.149316 0.779823 0.0690126julia> x[:, 2] # get the second column.4-element Array{Float64,1}: 0.186253 0.894781 0.18859 0.779823julia> x[1, :] # get the first row.1x3 Array{Float64,2}: 0.323877 0.186253 0.600605julia> x [ 1 : 2 , 2 : 3 ] # получаем подматрицу, охватывающую строки 1, 2 и столбцы 2, 3 2x2 Array{Float64,2}: 0.186253 0.600605 0.894781 0.0955007  

Смотрите также

Рекомендации

  1. ^ Zhang, Zemin; Аэрон, Щучин (15 марта 2017 г.). «Точное тензорное завершение с использованием t-SVD». Транзакции IEEE по обработке сигналов . 65 (6). Институт инженеров по электротехнике и электронике (IEEE): 1511–1526. arXiv : 1502.04689 . дои : 10.1109/tsp.2016.2639466 . ISSN  1053-587X.
  2. ^ ab IBM Corporation (1995). Справочник по языкам PL/I для MVS и VM .
  3. ^ «Прохождение 10-летней отметки» . Измерение журнала . Hewlett Packard. Октябрь 1976.
  4. ^ Миллман, К. Джаррод; Айвазис, Михаил (2011). «Python для ученых и инженеров». Вычисления в науке и технике . 13 (2): 9–12. дои : 10.1109/MCSE.2011.36.