Б. Страуструп - Язык программирования С++. Специальное издание, 3-изд. Бином. 2004 (1160791), страница 168
Текст из файла (страница 168)
Можно вообразить (хотя н с трудом) стандартный библиотечный класс сотр1ех в другом представлении. Отметим использование шаблонов членов для инициализации и присваивания ему любого другого типа сотр1ех любым другим Я 13.6.2). На протяжении отой книги я использовал сотр(ех в качестве класса, а не шаблона. Это' приемлемо, так как я использовал фокус с пространством имев, чтобы получить тип со(лр1ех с а(оиб(е, который я обычно предпочитаю: (урес(е/к(г(ссотр(ех<((оиЫе> сотр1ех; Определены обычные унарные и бинарные операции: 1етр!а(е<с(азз Т> сотр!ех<Т> орска(ог+ (сопя( сотр!ех -Т й, сопк1 сотр!ех<7>йг 1етр!а(е<с!азк Т> сотр!ех<Т орега1ог+ (соля(сотр!ех<Т й, сопя( Тй! 1етр1а1е<с!акз Т> сотр!ех<Т орега1оге (сопя( Тй, сопя( сотр!ех<Т й) // аналогично: —, *, /, == и!= 1етр!а1е<с!акк Т сотр!ех<Т орега1ог+ (сопя( сотр!ех<Т>й)1 1етр(а1е<с1аяз Т> сотр!ех<Т орега1ог — (сопя( сотр!ех Т й! Введены координатные функции; 1етр!а1е<с!азз Т> Тгеа1 (солк1 сотр(ех<7>й(; (етр!а1е<с!азк Т Т(тау(сопя(сотр1ех<Т &1 1етр(а1е<с!аяя Т> сот р!ех<Т соп((сопя( сотр!ех<Т й(; // конструирует из полярных координат (айк(), агуО): (етр(а(с<с!акз 7> сотр1ех<T ро!аг (солз1 Тз гйо, сопя( Тй (йе(а~; 1етр!а1е<с!азз Т> Т айз (сопк1 сотр!ех<Т й( //иногда называется гйо (р) (е(пр!а(е<с(акз Т Т агу(солз1 сотр!ех<Т>й), // иногда называется (йе(а (0) 1етр1а(е<с!азз Т> Тпогт (сопя( сотр!ех<Т>й) // квадрат айяО Обеспечивается обычный набор математических функций: 1етр!а1е<с!акк Т> сотр(ех<Т з!п(сопя(сотр!ех<7 Ц; // аналог(тно: тлй, (ап, 1апй, соя, созй, ехр, !оу и !оу! 0 749 22.6.
Обобщенные числовые алгоритмы 1етр!а1е<с1аяя Т> совр!ех<Т роге (сопя1сотр!ех<Т'й, !л1); 1етр!а1е<с1аяк Т> готр!ех<Т роп> (сопя1 сотр(ех<Т й, сопят' Тй) 1етр1и1е<с!азя Т» сотр1ех<Т рот (соля1 сотр!ех<Т й, сопя! сотр1ех<Т й)> 1етр!а1е<с!а«я Т> сотр!ех<Т рол>(соля1 Тй, сопя! сотр!ех<Т й); И наконец, предоставляется потоковый ввод/вывод: 1етр!а1е<с1аяя Т, с1аяя СЬ, с1аяя Т>. Ьая!с 1яггеат<СЬ, Тг>й орега1ог» (бак!с 1яггеат<СЬ, Тг й, сотр(ех<Т»й), 1етр1а1е<с!аяя Т, с! ияз СЬ, с! аяя Тг> Ьаягс оявеат<СЬ, Тг й орегагог (Ьоя1с ояггеат<СБ, Тг>й,сопя1сотр!ех<Т й)> Комплексное число записывается в формате (х, у) ц может быть считано в формате х, (х) и (х, у) (х 21.2 3, 5 21.3.5). Специализации сотр1ех<Яоа1>, сотр1ех<г/ои61е> и сотр!ех<1опд к!оиЫе> введены для сокращения преобразований Я 13.6.2) и чтобы предоставить возможность оптимизации, Например: сотр!ех(йоиЫе> =00,г!оиЫе(=0.0): ге(>),ил (!) () сотр!ех (сопя!катр!ех</!оа1>й а); > е (а.геа! ()), !т (а!тау ()) () ехрас!1 сотр(ех (сопя! сотр!ех <!пну >1оиЫе>й а), ге (а геа! ()), !т (а (т ау ()) () Теперь катр!ехала!> может быть преобразовано в сотр!ех<г/оиЫе>, в то время как сотр1ех<!опд г/ои6!е> не может.
Аналогично специализации гарантируют, что сотр1ех<Яоа1> и сотр!ех<г/ои6!е> могут быть «тихо» преобразованы в сотр!ех<!олу' г/ои6!е>, но сотр!ех<(опус!ои6!е> не может бьггь неявно преобразовано в сотр(ех<г)ои6!е> или сотр1ех</!оа(>, а сотр(ех йои61е> не преобразуется неявно в сотр(ехала!>. Забавно, что присвоение не предлагает такой же защигы, как конструкторы.
Например: оогс!Ясотр1ех</!оаг> с/, сотр!ех<доиЫе> сб, сотр1ех<!олу боиЫе> сЫ, сотр!ех<1п1> с1) ( // правильно, но будпге осторожны // правильно // правильно с! = с!<1; с1= сД с1 = сй 22.6. Обобщенные числовые алгоритмы В <питег!с> стандартная библиотека предоставляет несколько обобщенных числен- ных алгоритмов в стиле нечисленных алгоритмов из <а1уог116т> (глава 18): 1етр!а1е<' с(аяк сотр!ех< >1оиЫе> ( >1оиЫе ге, !т; риЬЙс. 1урес!е1с!ои6!е оа1ие 1уре; сотр!ех<боиЫе> с! =с/; сотр1ех<бои61е> с2 = сс(, сотр!ех<с!оиЫе> су= сЫ; сотр1ех<уоиЫе> с4 (с!О); сотр(ех<иоиЫе> об= с1, // хорошо О хорошо // ошибка возки>жно урезание // правильно> вь> попросили урезать // ошибка: нет преобразования 750 Глава 22. Численные методы Обобщенные числовые алгоритмы <пшпег)с> Эти алгоритмы обобщают обычные операции, такие как вычисление суммы, позволяя применять пх ко всем видам послсдовательностей и задавая в виде параметров операцию, которую' необходимо применить к элементам последовательностей.
Для каждого алгоритма универсальная версия дополняется версией, применяющей наиболее распространенный для данного алгоритма оператор. 22.8.1. Накопление Алгоритм ассити1а1е () можно представить как обобщение суммы элементов вектора. Алгоритм ассити1а1е () опрелеляется в пространстве имен к!1!и представлен в <питепс>; 1етр!а1е<с!акк Тп, с!акк Т> Т ассати!а1е (1п„Г!гк1, Тп 1ак1, Т т!1) ( гоЬПе (/!гк1!= !акс) ши= ии1+ *Як!+~-; // плюс ге!игл !п!1; ) 1етр!а!екс!акк !и, с!акк Т, с!акк ВтОр> Тоссити1а1е(!п/!гк1 1п !ак1, Т!пи Втор ар) ( и!и!е фгк1!= !ак1) !пи = ор (гп11, 'г!гк1+л-~! ге1игп !и!1, ) // универсальнал операция Нростая версия ассити!а1е () складывает элементы последовательности, используя их оператор +.
Например: ооЫ Т(оес1огл !пт>й рнсе, !!к1л/!оа1>й гпсг) //накопловоея в !п! //накоплнваел в с!оные т11 = а сошли!а ге ~)рг1се.Ьедш (), рг!се. епк! (), О); ИоиЫе 0 = 0; 0 = ассити1а1е (!псгЬея!и (), спсг,епс! (), 0); //.. Обратите внимание на то, как тип начального переданного значения определяет тип результата. Не все элементы, которые мы хотим добавить, доступны как элементы последовательности. Если это действительно так, зачастую можно обеспечить операцию, которая вызывалась бы из ассити!аге () для создания добавляемых элементов по мере по- ассити1а1е () тпегргос/ис1 () раг1!а1 кит () агЦасеп1 с1!Дегепсе () Накапливает результаты операции над последовательностью Накапливает результаты операции над двумя последовательностями Генерирует последовательность по операции над последовательностью Генерирует последовательность по операции над последовательностью 751 22,6. Обобщенные числовые алгоритмы стуцленьсч. Среди кандидатов на роль передаваемой операции самым очевидным явля- ется извлечение значения из структуры данных.
Например; з1 ис1 Ресотс(( 0- ип ишгрг!се; !п1пшпЬег о)' ипИз, !опу рпсе (!опуса!, сопз1 Кесотуй ~) ( те1игп оа)е г.ипИ рпсе*гпитЬет о! ипИз; оо!61'(соля! оес1ог<!(есогс!>й о) ( сои! « 'Итого. " «асс ит и1 а!е (о Ьеугп (), о спс! (), О, р псе) « '~л'; Операпии, подобные ассити(а1е, в некоторых сообществах называются тес(исе и тес)ис1!ол (приведение). 22.Б.2. Алгоритм (ппег ргос(ос1 Накопление из последовательности очень распространено, но накопление из двух последовательностей тоже не является редкостью.
Алгоритм !апет рсоа(ис1 () определен в пространстве имен я1с(и представлен в <питепс>: 1етр!а1е<с1азз 1и, с1азз 1п2, с1азз Т> Т !лпегртос!ис! (1п1)гя1, 1п 1аз1, 1п2Яз12, Т !л11) тдуе (!)тз1 1= !аз!) !лИ =ип1 <-"Яг>1<+" 11тз12<. -; ге1игп !пИ; 1етпр!а!с<с!а <з 1п, с!азз 1п2, с1азз Т, с1аяз Втор, с1азя Вгпор2> Т (лпег ртоуис1 (1п11 к1 1п 1азт 1л21)гз12, Т!пИ В!лор ор В(пор2 ор2) ( тАИе (Вгз1! = 1аз1) 1пИ = оР (ЫИ, оР2 (1)тз1<-ь, "1)тз12е<-)); те1игп !лИ; Как обычно, в качестве аргумента передается только начало второй входной последовательности. Считается, что вторая входная последовательность по крайней мере такой же длины, что и первая. Алгоритм !плес ргоа1ис! является ключевой операцией при умножении матрицы Ма1пх на вектор оа1аггау: оа!аттау<с!оиЫе> орега1от' (сопз1 Ма1гйсй т, оа!актау<ИоиЫе>й о) ( оа1агтау<ИоиЫе> гез (т.с(!т2 ()); Тот (з1ге 11=0;!<т сут2();!<-ь)( соаз1 Сзйсе Иег<ОоиЫе>й т! = т тот (!); 752 Глава 22.
Численные методы гез [1) = 1 иле грго<!ис1 (и', и'.ел<! )), ! о[0], г!пи 6!е (0)); ге1игп гек; ) оа!аггау<Ооиб!е> орегагог" (оа!аггау<>! о, соля!Ма!с!хо т] ( оа!аггау<Ооиб!е> гек (т.й!т! ()); 1ог (яссе 1! = О;1<тя1!т1 [); й->) ( сопя!Се!!се !1ег<!!оиб!е>8 с! = т.со1итп [1); гез [!) = )плес рго!!исг (с1, обет!, Во[О), Ооиб!е (О)); ге1игл гея; ) Некоторые разновидности алгоритма !ллегргог[ис! часто называют «скюирным про- изведением» (с)от ргодпсС). 22.6.3. Инкрементное изменение Алгоритмы раг1[а1 яит () и аЯасеп1 йфегепсе () являются обратными по отношению друг к другу и связаны с понятием инкрементного изменения.
Они определены в пространстве имен я1а! и представлены в <питег(с>: 1етр!а1е<с!акк 1п, с!азя Оип> Ои1 аЩасеп1 ЙДегепсе(1пуик1, 1и !ак1, Ои1гез); 1етр!а1е<с!аяк Ьь с!аяк Ои1, с!азз В!пор> Ои! а 4а сеп1 <Щегеп се )!п 1) ге 1, Ьл !ак1, Оиг гея, В!п Ор ор); Получив последовательность а, Ь, с, 0 и т. д., ас[1асел1 й1[егелсе выдаст а, Ь-а, с-Ь, а1-си т. д. Рассмотрим вектор с последовательностью замеров температуры. Мы можем преобразовать его в вектор изменений температуры: оестог<Ооиб!е> 1еглрк; ооиЩ [ афасеп1 ЖЯегепсе фетре.беу!п (), 1етрк.ет! (), 1етрз.беу1л ()); Например, 17, 19, 20, 20, 1 7 превратится в 17, 2, 1, О, -Я.
Алгоритм раг1!а! яит, наоборот, позволяет нам вычислить конечный результат набора инкрементных изменений: 1етр!а1е<с!оке 1п, с1акз Ои1, с!акз Втор> Ои1 раг1!а! зит (1п1)гя1, 1п !ак1, Ои1 гек, ВтОр ор) ( Ц' фгя! == !ак1) ге1игп гея; *гея = *Ягк1; 7оа)= *Ягк1; гол!!е (~-фгзг!= 1аз1) ( оа! = ор (оа1, "1!гя1! 753 22.7. Случайные числа *~-+сев = оа1; ге!игп ч-чгев; !етрlа!е<с!авв1п, с!иве Ои!> Ои!рагс!а! зит (1п ага!, 1и lавс, Ои! гев) ( ге!игп раз!!а! зит (/)гвг, !аз!, гев, р1ив) // у 18.4.3 Получив последовательность а, Ь, с, с( и т.
д., раг11а1 зит выдаст а, а+Ь, а+Ь+с, а4Ь4с+!1 и т. д. Например: поЫ/() ( рагио! вит (!етрз сйапуевйеут (), !етрв сйапдев.епс1(), !етрв.беугп 8); ) Обратите внимание на то, как раг11а! вит () увеличивает гез перед присваиванием нового значения через него.