Бьерн Страуструп. Язык программирования С++. Специальное издание (2011) (1004033), страница 169
Текст из файла (страница 169)
Трудно, однако, представить что-либо иное для стандартного библиотечного сотр!ех. Обратите здесь внимание на шаблоны в качестве членов сотр!ех — они обеспечивают инициализацию и присваивание комплексных чисел с другим скалярным типом (513.6.2). На протяжении всей книги я использовал сотр1ех в качестве класса, а не шаблона. Это допустимо из-за небольшого фокуса с пространством имен и оператором (урейеу. (урейе! з(й:: сотр(ех<йоиЫе> сотр1ех; Для сошр1ех определяются обычные унарные и бинарные операции: (етр(а(е<с(ат Т> сотр(ех< Т> орега(ог+ (сот( сотр(ех<Т> и, сот( сотр1ех< Т> и ) (етр(а(е<с(азк Т> сотр(ех<Т> орега(ог+ (<опт сотр(ех<Т> ь, сопл( Ти); (етр(а(е<с(азз Т> сотр!ех<Т орега(огь(сопи Ть, сот(сотр(ех<Т>ь); й'аналогично: -, *, 1 == и /= (етр1а(е<с1азз Т> сотр(ех<Т> оре«а(огь (сопл( сотр(ах< Т>ь ) ( (етрй((е<с(акз Т> сотр1ех<Т> орега(ог- (сопз( сотр1ех<Т> и ) ( Имеются координатные функции: (етр!а(е<с(азз Т> Т геа1 (сопя( сотр1ех<Т> и) ( (етр(а(е<с!ат Т> Т !тая ( сопз( сотр!ех< Т> и ) ( (етр(а(е<с1азз Т> сотр1ех<Т> соп! (сот( сотр(ех<Т> ь) ( У конструируется из полярных координат (айк(),ага())( (етр!а(е<с(тз Т> сотр(ех<Т> ро!аг (сот( Ть гйо, сопз( Ть ейе(а) (етр(а(е<с!ат Т> Т аЬк(сопл( сотрйх<Т>и) (етр(а(е<с(акк Т> Т ага (сопл( сотр1ех< Т> и ) (етр1а(е<с1ат Т> Т поет (сот( сотр(ех<Т> ь); р квадрат аЬкр 800 Предоставляются обычные математические функции: <етр!а<е<с!ат Т> сотр<ех<Т> Ып (солги сотр<ех<Т> ь ); //аналогично< Ылб, зо «, ал, <алЬ, соя, сояЬ, ехр, !ое и!ое10 <етр!а<е<с!азя Т> сотр<ех<Т> ро<г (сопя< сотр<ех<Т> ь, 1п<); <етр1а<е<с<аяя Т> сотр<ех<Т> ро<г(солги сотр<ех<Т> ь, сопя< Ть) < <етр<а<е<с1аяя Т> сотр<ех<Т> ро<г(сопя< сотр!ех<Т> ь, сопи сотр1ех<Т> ь) <етр<а<е<с<аяя Т> сотр<ех<Т> ром (солги Ть, солт сотр<ех<Т> ь); И, наконец, обеспечивается потоковый ввод/вывод: <етр<а<е<с<аяя Т, с<лез СЬ, с1аяя Тг> Ьамс !я<геат<СЬ, Тг ь орега<ог» (Ьаис Ы<геат<СЬ, Тг>ь, сотр<ех<Т>ь); <етр<а<е<с!аяя Т, с1ат СЬ, с<а<я Тг> Ьаяк оз<геат<СЬ, Тг>ь орега<ог«(Ьаяс о<егеат<СЬ, Тг>ь, солт сотр1ех<Т>ь) Комплексные числа выводятся в формате (х, у), и могут читаться в форматах х, (х) и (х,у) (в2).2.3, в21.3.5).
Специализации сотр1ех<9оаг>, сотр!ех«!оиЫе> и сотр1ех<!оие <!оиЫе> введены для ограничения необходимости в преобразованиях типа (В)3.6.2) н для оптимизации. Например: <етр<а<е< > с<вяз сотр<ех«<оиЫе> ( «оиЫе «е, <т< риЫ<с: 0<ре«еГ«оиЫе га1ие <уре; сотр!ех(«оиЫе г = 0.0, «оиЫе < =- О.О): ге(г), <т(<) () сотр<ех(солт сотр!ах<!<ли<>ь а): ге(а.геа<() ), <т (а.!тая() ) ( ) ехр1кисотр1ех(сопя< сотр<ех<<опе«оиЫе>ь а) < ге(а.геа1() ), ил(а.1таи() ) () // )< Теперь сотр!ех<Яоаг> может «тихо» преобразовываться в сотр1ех«!оиЫе>, в то время как сотр1ех<1опя <!оиЫе> — нет.
Аналогично, специализации гарантируют неявные преобразования сотр1ех<!1оаг> и сотр1ех«1оиЫе> в сотр1ех<!опя <1оиЫе>, а обратные преобразования — нет. Забавно, что присваивания подобной зашиты не предоставляют. Например: = с«< = сЫ< (сЫ) ) = с1< с1 = с!4< //оФ, но будьте осторожны с1 = с4< //о« с1 = с<; //о« гоЫ 1'(сотр!ех<)1 оа<> сотр<сх<т<> с<) ( сотр1ех«<оиЫе> с1 сотр<ех«<оиЫе> с1 сотр<ех«<оиЫе> с3 сотр1ех«<оиЫе> с4 сотр1ех«<оиЫе> с5 Глава 22. Классы для математических вычислений сГ, сотр!ех«<оиЫе> с<<, сотр<ех<<опе <<оиЫе> сЖ, / чудесно // чудесно // еп ог: возможно усечение // о«г явное преобразование // ег.ог: нет преобразования 22.6 Обобщенные численные алгоритмы 801 22.6.
Обобщенные численные алгоритмы Обобщенные численн Аккумулиру последоват носат«1а1е ( ) 1пнег ргойис( () кумулиру следоват ~ рагс!а! зат () нерирует оследоват афасенг ЙДегепсе () нерирует последоват Эти алгоритмы обобщают обычные операции, например, вычисление суммы, позволяя применять их ко всем видам последовательностей и позволяя задавать в виде параметра операцию, применимую к их элементам. Каждый алгоритм сопровождается версией, применяющей наиболее типичную для данного алгоритма операцию.
22.6.1. Алгоритм ассиптм181е() Алгоритм ассити1«ге() есть обобщение суммирования элементов вектора. Он определяется в пространстве имен мИ и представлен в заголовочном файле <и«теис>; гегпр!а!е<с(аи зп, с1азз Т> Т асс«та(азе (1пу)гяг, 1п 1азг, Т (тз) «Ы1е (Тзгяз ! = Ьзяг) шй = ««1 з "~из!;-ч-; гезиги (пВ; ) гетр!иге<с(азз 1и, с(азз Т, с(азз В(пОр> Т ассити1азе (1п Ягяг, !и 1ая1, Т 1пй, ВтОр ор) ( и ьее (Ттгяз ! = 1аяз) 1тг = ор (1пи, 'уггягт-е ); ге!ига 1и!1; (г Простая версия ассити!аге() суммирует элементы последовательности, используя операцию + для ее элементов. Например: гоЫГ(гесгог<1т>я расе, 1!я!<!(оаг>з шсг) ( 1пг 1 .= асс«та(аге (рисе .
Ьел(п ( ), рмсе. ент( ( ), д) ао«Ые В = От В заголовочном файле <иитеис> стандартная библиотека предоставляет ряд обобщенных численных алгоритмов в стиле нечисленных алгоритмов из <а1ВогЫии> (глава ! 8): 802 Глава 22. Классы для математических вычислений << = ассити<а<е (<пег. Ьея<п (), 1псг. ел<< (), «) < <7... ) Обратите внимание на то, как тип переданного начального значения определяет тип возвращаемого значения. Не все элементы, которые мы хотим просуммировать, изначально доступны как элементы последовательности. В таком случае мы можем предоставить операцию, которая вызывалась бы из асстии1а<е () для создания добавляемых элементов. Чаше всего это требуется в случае, когда нужно извлекать добавляемые (суммируемые) значения из некоторой структуры данных.
Например: ял ис< Лесопг ( л' ... <и< илп рисе; т< питЬег о< ил<<я; 1опд рг<се (<оля га1, сопел Весне<<а г) ( ге<игл га< е г. ит< рг1се * г. питЬег о1 итм< ) гоЫ <' (соля< гес<ог<Весог«> а г) сои< « "Тога< го<не: " «а<сити<а<е ( г.
Ьедт ( ), г. еп«( ), В, рг<се ) « ' ',и '; ) 22.6.2. Алгоритм <олег ргодысЦ) Накопление из последовательности весьма распространенная задача. Но накопление из двух последовательностей тоже встречается не слишком редко. Алгоритм 1ппегрго<гис<О определен в пространстве имен ят<1 и представлен в заголовочном файле <литег(с>: <етр1а<е<с<аяя 1п, с<от 1п2, с1аяя Т> Т <нпег рго«и<<(1п 2<ге<, 1п <ая<, 1п21<гя<2, Т <и<<) ( <гЬ1<е (1<ге< ! = 1аял т1< = тп + *Ягя«-+ * *1тя<2++; ге<игл <пд< ) <етр<а<е<с1аяя 1п, с<от 1п2, с<от Т, с<ля< ВтОр, с<от В<пОр2> Т тпег рго«и<<(1п 2<ге<, 1л 1ая<, 1п2 <ге<<2, Т 1п<<, В1пОр ор, В1пОр2 ор2) ( <<Ь<1е (11<я< ! = <ая<) <т< = ор (1л<<, ор2 ("21<<<++, *1<ге<2++) ); ге<и<и <т<; ) Как обычно, в качестве аргумента передается только начало второй последовательности.
Считается, что вторая последовательность не короче первой последовательности. 22.б. Обобщенные численные алгоритмы 803 Алгоритм <ппег ргойис(() является ключевой операцией при умножении матрицы Мапзх на вектор га!а(тау: га(аггау<йоиЫе> орега<ог* (сопя< Ма(го<а т, га!аггау<йоид!е>а г) ( га(аггау<йоиЫе> гея (т. сат2 ( ) ); 1дг(нге (1= О( 1<т.й(т2() ( Ь+) ( сопя< Сяасе Ьег<йоиЫе>я п = т.го<я(!); гея [1] = <п пег р гойи с< ( и', п'.
епй ( ), а г [ О], йоиЫе ( 0) ) ге(игп гея( ) га1аггау<йоиЫе> прего<о(* (га(аггау<йоиЫе>а г, сопи Ма<пха т) ( га(аггау<йоиЫе> гея (т. гдт1 () ); 1ог(нге « = 0; 1<т.й(т! (); 1яя) ( сопя( Ся!(се Вег<йоиЫе> а с< =- т . со!итп (1)," гея[1] = тпег ргойис<(с1,<!.епй(), аз[0], йоиЫе(0) ) ге(игп гея( ) Некоторые формы алгоритма (ппег ргойис< ( ) называют скалярным произведением [йо( ргойис(). 22.6З. Приращения (!псгегпеп1а! с(тапяев) Алгоритмы раг((а1 яит ( ) н айуасеп~Щегеисе О обратны друг другу и работают с приращениями [а не с абсолютными значениями элементов). Они определены в пространстве имен я<й и представлены в заголовочном файле <пател!с>: <етр1а<е<с1аяя 1п, с!азз Ои<> Оп< айрасеп< йфегепсе(1п1ггя<, 1п (ат, Ои< гея] <етр!а<в<с(аяя 1и, <1аяя Ои<, с(аяз ВшОр> Ои< айрасеп( й5егепсе (1п <<гя<, 1п (ат, Ои< гея, ВтОр ор) Для последовательности а Ь с йи тл.