|
Программирование >> Разработка устойчивых систем
valarray<double> acc(v + sh); printCsum . асе): valarray<double> trig(s1n(v) + cos(acc)): printCtrig , trig): valarray<double> p(pow(v. 3.0)): print( 3rd power , p): valarray<double> app(v.apply(f)): print( f(v) , app): valarray<bool> eq(v == app): print( v == app? . eq): double X = v.minO double у = v.maxO: double z = v.sumO cout x = X . у = у z = z endl: } III:- В классе valarray определен конструктор, которому передается массив базового типа и количество элементов массива, требуемых для инициализации valarray. Функция shift() сдвигает все элементы valarray на одну позицию влево (или вправо при отрицательном значении аргумента) и заполняет освободившиеся места значением по умолчанию для базового типа (О в данном случае). Также имеется функция cshift() для выполнения циклического сдвига. Все математические операторы и функции перегружены для работы с объектами valarrray, а бинарные операторы требуют, чтобы аргументы valarray имели одинаковые базовые тип и размер. Функция applyO по аналогии с алгоритмом transform() при.меняет функцию к каждому элементу, но результаты собираются в итоговый объект valarray. Операторы сравнения возвращают объекты valarray<bool> соответствующего размера с результатами поэлементных сравнений (см. eq в предыдущем примере). Большинство операций возвращает новый объект valarray, но некоторые операции (такие как min(), max() и sum()) по очевидным причинам возвращают скалярную величину. Однако самая необычная операция с valarray - выделение подмножеств элементов, причем не только для получения информации, но и для ее обновления. Подмножество элементов valarray называется срезом. Срезы используются некоторыми операторами. Следующий пример демонстрирует работу со срезами: : C07:Valarray2.cpp {-bor}{-dmc} Срезы и маски #include PrintValarray.h using namespace std: int mainO { int data[] = {1,2.3.4.5.6.7,8.9.10.11.12}; valarray<int> v(data. 12); valarray<int> rl(v[slice(0. 4. 3)]): print( slice(0,4,3) . rl); Выделение элементов по условию valarray<int> r2(v[v > 6]): print( elements > 6 , r2); Возведение в квадрат первого столбца v[slice(0, 4, 3)] *= valarray<int>(v[slice(0, 4. 3)]): print( after squaring first column , v); Восстановление исходных значений int idx[] = {1.4,7,10}; valarray<int> save(Tdx, 4): v[slice(0, 4. 3)] = save; printCv restored , v): Выделение двухмерного подмножества: {{1. 3. 5}. {7. 9. 11}} valarray<size t> siz(2): siz[0] = 2: siz[l] = 3: valarray<size t> gap(2): gap[0] = 6: gapEl] = 2: valarray<int> r3(v[gslice(0. siz. gap)]): print( 2-d slice . r3): Выделение подмножества по логической маске (элементы bool) valarray<bool> maskCfalse, 5): mask[l] = mask[2] = mask[4] = true: valarray<int> r4(v[mask]): print( v[mask] . r4): Выделение подмножества по индексной маске (элементы size t) size t idx2[] = {2.2.3.6}: valarray<size t> mask2(idx2. 4): valarray<int> r5(v[mask2]): print( v[mask2] . r5): Использование индексной маски при присваивании valarray<char> text( now is the time . 15): valarray<char> caps( NITT . 4): valarray<size t> idx3(4): idx3[0] = 0: idx3[l] = 4: idx3[2] = 7: idx3[3] = 11: text[idx3] = caps: print( capitalized . text): } /:- Конструктор slice получает три аргумента: начальный индекс, количество выделяемых элементов и шаг (расстояние между нужными элементами). Срезы могут использоваться для индексации сушествующих объектов valarray; при этом возвращается новый объект valarray с выделенными элементами. Объект valarray с элементами bool (такой, как полученный при выделении элементов по условию V > б в нашем примере) может потребоваться для индексирования других объектов valarray. При этом из целевого массива выделяются элементы, соответствующие истинным элементам маски. Как видно из приведенного примера, срезы и маски также могут применяться в качестве индексов слева от оператора присваивания. Обобщенные срезы gslice (от generalized slice ) в целом аналогичны срезам, однако количество элементов и шаги индексирования для них задаются массивами, что позволяет интерпретировать valarray как многомерный массив. В предыдущем примере из v выделяется подмассив 2 х 3, в котором индексы по одному измерению находятся в V на расстоянии 6 элементов, а по другому - на расстоянии двух элементов. Таким образом, фактически извлекается матрица: 1 3 5 7 9 11 Результат выполнения программы выглядит так: slice(0.4.3): 1 4 7 10 elements > 6: 7 8 9 10 after squaring v: 1 2 3 16 5 6 49 8 9 100 11 12 V restored: 1 2 3 4 5 6 7 8 9 10 11 12 2-d slice: 1 3 5 7 9 11 vEmask]: 2 3 5 v[mask2]: 3 3 4 7 capitalized: Now Is The Time Одним из примеров практического применения срезов является умножение матриц. Посмотрим, как должна выглядеть функция для умножения двух целочисленных матриц при использовании обычных массивов: void matmultCconst int a[][MAXCOLS]. size t m. size t n. const int b[][MAXCOLS]. size t p. size t q. int result[][MAXCOLS): Функция умножает матрицу a с размерами mxn на матрицу b с размерами pxq; предполагается, что пир равны. Как видите, без применения объекта valarray или его аналога приходится фиксировать максимальную вторую размерность в каждой матрице. Кроме того, такой подход затрудняет возвращение массива-результата по значению, поэтому вызывающая сторона обычно передает его в дополнительном аргументе. Объекты valarray не только позволяют передавать матрицы произвольного размера, но и упрощают обработку матриц любого типа и возврат результата по значению. Вот как это делается: : C07:MatrixMultiply.cpp Умножение матриц с использованием объектов valarray #include <cassert> #include <cstddef> #include <cmath> linclude <iostream> linclude <iomanip> linclude <valarray> using namespace std: Вывод объекта valarray в виде матрицы tempiate<cl ass T> void printMatrix(const valarray<T>& a. size t n) { size t siz = n*n: assertCsiz <= a.sizeO): for(size t i = 0: i < siz: ++i) { cout setw(5) a[i]: cout ((i+l)n ? : \n): cout endl: Умножение совместимых матриц в формате valarray tempiate<class T> valarray<T> matmultCconst valarray<T>& a. size t arows. size t acols. const valarray<T>& b. size t brows, size t bcols) { assert(acols == brows): valarray<T> result(arows * bcols): for(size t i = 0: i < arows: ++i) for(size t j = 0: j < bcols: ++j) { Внутреннее произведение строки a[i] и столбца b[j] valarray<T> row = a[slice(acols*i. acols. 1)]: valarray<T> col = b[slice(j. brows, bcols)]: result[i*bcols + j] = (row * coD.sumO:
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки. |