Действительно ли порядок строк и столбцов является свойством языка программирования

#matrix #language-agnostic #terminology

#матрица #язык не зависит от языка #терминология

Вопрос:

Я думаю, что обнаружил широко распространенное недоразумение (профессора делают это неправильно!). Люди говорят, что C и C представляют матрицы в порядке следования строк и в порядке следования столбцов Fortran. Но я сомневаюсь, что C и C имеют сборку в основном порядке, потому что нет истинного типа матрицы? Если я войду

 int A[2][3] = { {1, 2, 3}
              , {4, 5, 6} };
  

Порядок является основным только потому, что мой редактор ориентирован на строки, а не на столбцы. Это не имеет никакого отношения к самому языку, или не имеет? Если бы редактор был ориентирован на столбцы:

 i {
n { {
t 1 4
  , ,
A 2 5
[ , ,
2 3 6
] } }
[   ;
3 
]
=
  

Теперь матрица A имеет два столбца и три строки.

Чтобы проиллюстрировать далее, рассмотрим цикл печати матрицы

 for(int k=0; k<M;   k)
    {
    for(int l=0; l<N;   l)
        {printf("%.7gt",A[k][l]);}
    putchar('n');
    }
  

Почему он печатается по строкам? Потому что ‘n’ перемещается в следующую строку, а не в следующий столбец. Если ‘n’ было интерпретировано как «перейти к следующему столбцу и первой строке», а ‘t’ перейти к следующей строке, то A печатается по столбцам. Но я знаю, что мой терминал ориентирован на строки, поэтому, если я хочу печатать по столбцам, единственный способ — поменять местами эти циклы.

Если A [k] логически представляет строку или столбец, зависит от функций, которые работают с A, а затем есть компромисс, какой порядок выбрать. Например, исключение Гаусса rows{column,rows{column}} . Преимущество размещения индекса строки в первую очередь заключается в том, что это упрощает замену строк при повороте. Однако для выполнения поворота необходимо перебирать все строки в одном столбце, что должно быть быстрее, если выбрать противоположное. Самый внутренний цикл исключения имеет доступ к двум строкам одновременно, и ни одна из них не является действительно хорошей.

Лучшей терминологией, вероятно, является индексация по первому индексу и индексация по последнему индексу. Это чисто языковая особенность: индексация по первому индексу относится к ситуации, когда предполагается, что первый заданный индекс увеличивается медленнее всего, в то время как индексация по последнему индексу противоположна. «Строки» и «столбцы» — это проблема интерпретации, очень похожая на порядок байтов и кодировки символов: компилятор никогда не узнает, что такое строка или столбец, но он может иметь определенный языком порядок ввода (большинство языков принимают числовые константы в порядке большого конца, но моему компьютеру нужен маленький конец).). Эти термины взяты из соглашений в среде и библиотечных подпрограммах.

Комментарии:

1. Я тоже часто думал об этом, и я согласен. На самом деле порядок индексов определяется языком, а не фактическим 2d-расположением данных (потому что в любом случае все это просто линейно). Люди яростно возражают против этого мнения в Интернете и предполагают, что вы в замешательстве. Решаете ли вы называть первый или последний индекс «строкой», зависит от вас.

2. Но, как примечание, вы будете против установленного стандарта… поэтому большинство библиотек будут использовать 2d-макет для вашей линейной памяти.

3. @JonathanOlson я нашел другую неплохую терминологию: AoS и SoA. Хотя столбцы матрицы не имеют «имен», они могут быть коэффициентами для линейной системы уравнений. Таким образом, вы можете присвоить им соответствующее имя.

Ответ №1:

Это не имеет ничего общего с тем, как работает ваш текстовый редактор, и все связано с тем, как элементы 2D-массива расположены в памяти. Это, в свою очередь, определяет, является ли более эффективным для вложенных циклов (перебор всех элементов матрицы) более эффективным с циклом строк в качестве внутреннего цикла или с циклом столбцов в качестве внутреннего цикла.

Комментарии:

1. Я указываю на то, что в памяти нет строк или столбцов. Все, что есть, это массив цифр. Строки и столбцы являются только представлением данных.

Ответ №2:

Как предположил один из комментаторов, на самом деле это просто порядок индексов в синтаксисе доступа к массиву, который делает C основным для строк.

Вот лучший пример программы, которая инициализирует 2D-массив, используя плоский список значений.

 #include <stdio.h>
#include <string.h>

int main() {
    int data[9] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    int arr[3][3];
    memcpy(arr, data, sizeof(int)*9);

    printf("arr[0][1] = %dn", arr[0][1]);
}
  

Итак, теперь мы можем избежать путаницы, добавленной синтаксисом объявления 2D-массива или тем, как этот синтаксис изложен в текстовом редакторе. Нас просто интересует, как C интерпретирует линейный список значений, которые мы поместили в память.

И если мы запустим программу, мы увидим:

 $ ./a.out 
arr[0][1] = 2
  

Это то, что делает C основным строкой. Тот факт, что синтаксис массива интерпретируется как [строка] [столбец] при доступе к данным в памяти.