Бьерн Страуструп. Язык программирования С++. Специальное издание (2011) (1004033), страница 170
Текст из файла (страница 170)
а4асеп( <В(уегепсе () выдаст а, Ь-а с-Ьй-с и тл. Рассмотрим вектор температурных показаний. Его можно преобразовать в вектор температурных приращений следующим образом: гес<ог<йоиЫе> <етря( го(й1'( ) ай!асвп( ЙЯегепсе ((етря.
Ьея(п ( ), <етря . епй ( ), <етря. Ьея(п ( ) ) ( ) К примеру, последовательность показаний 17, 19, 20, 20, 17 превратится в 17, 2, 1,0,-3. Алгоритм рагг!а! яит (), наоборот, позволяет получить последовательность значений из последовательности приращений: Глава 22. Классы для математических вычислений 80Я <етр<а<е<с<аяя 1п, с<аяя Ош, с!аяя В(пОр> Ошрагба! кит (!ар«я<, 1п !аш, Ош гея, ВтОр ор) ( (Т(((«я<==!ая<) ге<игл «ею< *гея = *!югя« урепате Вега<ог <гайя<1п>:: га<ие <уре «а! ен1!«я« ~Усек К19.2.2 <«Ы!е(ь+В«я< (= !ат) ( га! = ор ( «а<, '1<«я<) < *++«ел = «ае ге<и«п ~-ь«ея< ) <етр!а<е<с<аяя 1и, с!аяя Ои<> Оп< рог<(а! яит (1п1<гя<, 1п 1ат, Ош «ез) ( «е<игп ра«<ш! яит (!из<, !ат, гея, р<ия) < гУ К18А.З Например, из а, Ь, с, <! и т.д.
рагпа! килю() производит последовательность а, аьЬ, а+Ь+с, а+Ь+сь<! и т.д. Например: го!« 7() ( рог<<а! яит (<е<пря. Ьея!и ( ), <етрз. епд ( ), <етря. Ьед(п ( ) ); Обратите внимание на то, как рагпа! зит () инкрементирует гев перед присвоением через него нового значения. Это позволяет в качестве выходной последовательности использовать входную последовательность; ра«<!а! кп<п() ведет себя аналогично. Так, код ра«<<а! зит (г. Ьее!и (), «.еп«(), «.Ьее!и () ) < преврац(ает последовательность а, Ь, с, <! в а, а+Ь, а+Ььс, алЬ+с+<! и т.д., а код а<Ь1асеп< йЯе«енсе («.Ьее!и (), «.еп<((), «.Ьее(п() ) < возвратит последовательность в ее начальное состояние.
В частности, ра«<!а! кп<п () превратит 17, 2, 1, О, -3 в 17, 19, 30, 20, 17. Зти две операции полезны при анализе изменений любых значений. Например, анализ изменений курса акций нуждается именно в этих операциях. 22.7. Случайные числа Случайные числа очень важны для моделирования и программирования игр. В заголовочных файлах <ск«!!!Ь> и <м<!!!Ь. Ь> стандартная библиотека предоставляет простые базовые средства для генерации случайных чисел: Ие<<пе ВА)УО МАХ !тр!етеп<а6оп «е!)не<< I* большое положительное число I 22.7 Случайные числа 80$ ии гапй(); //псевдослучайное число мехсду О и АА1»2) МАХ гоЫ згаи4(ипз!8пе4 (п! з); У инициализирует генератор случайных чисел числом ! с1ат Колй!и! иив18пе4 1оп8 гапйх; //равномерное распределение; полагаем 32-Ь!! !ол8 риЫ)с: йап4!из(!оп8 з = О) (гапех=з; ) гоЫзее4(1ол8 з) (гапех=з; ) //магические числа позволяют использовать 3! бит из 32-битного!оп8: з!айс 1олл аЬз (1ол8 х) (ге!игл хьвх7ЯЩ~! ) зза!Ы 4оиЫе тих () [ге!игл 2147483648.
О; ) У внимание: доиЫе 1оп8 4гаи () ( гетгп гапйх = галйх * 1103515245» 12345; ) ИоиЫе(4гав() (ге!игл аЬз(4гаы() ) /тах(); ) //интервал (ОЦ 1оп8 орегагог() () (гетгп аЬз(4гал() ) ! ) У интервал (Оро»«(231Д с1ахв Г/гап4: ривг(с Канали» //равномерное распределение в интервале (О'и( 1оид и; риЬНс: и 4(! 8 ) (п= 1ол8 орегагог() () (1оп8 г = п«Яга»г(); ге!игл (с==и) ? и-1: г! ) ): с(азз Егапй: риЫ!с йаи41п! У экслоненциольное распределение случайных чисел ( 1оп8 теаи; Создать хороший генератор случайных чисел не так легко и, к сожалению, не все системы располагают качественной функцией гаиА() .
В частности, младшие биты в случайных числах часто вызывают подозрение, так что гаи«1() ьл — это не совсем хороший переносимый способ генерирования случайных от О до п-1. Часто, однако, приемлемый результат получается в результате вычисления выражения 1иг( (ИоиЫе(гаи«1() ) /ЯАК1г МАХ) *и) . В случае серьезных применений этой формулы нужно позаботиться еше о том, чтобы результат равнялся и с минимальнейшей вероятностью. Вызов функции згаиИ() инициирует новую последовательность случайных чисел из начального числа веем («из семени»), заданного в качестве аргумента этой функции. Для отладки важно, чтобы последовательность случайных чисел из заданного «семени» была воспроизводимой.
В то же время, бывает нужно, чтобы каждый запуск программы использовал разное «семя» для генерации случайных чисел: например, для непредсказуемости хода игры хорошее семя получается из битов таймера реального времени. Если вам нужно писать свой собственный генератор случайных чисел, настройтесь на его тщательное тестирование (822.9(14]). Генератор случайных чисел удобно реализовать в форме класса. В этом случае легко строятся генераторы случайных чисел с разными распределениями: 80б Глава 22.
Классы для математических вычислений рлЫ1с: Егапг((голи т) (теап=тг ) 1опхорегагог() () (геглгл -теап * 1оя( (тах() -г(гам () ) lтах() + .5) г ) )г Вот простой тест: гпг тагл () ( 11гапгГ Огаи (10) г тар<1лг, 1пг> Ьлсхеег Гог((пг » = Ог г< 1000000; 1»») ьлсьег[ггга»г() )++1 !ос (тг! = 0; 7<10; !++) соле «Ьлсхег(!) « ' ~п '; ) Если значения Ьисйег не равны приблизительно 100000, то в программе где-то закралась ошибка.
Эти генераторы случайных чисел являются слегка подредактированными версиями того, что я включал в первые выпуски библиотеки С++ (фактически, это было «С с классами»; $1,4) 22.8. Советы 1. Численные задачи часто весьма тонки. Если вы не на 100% уверены в математической стороне дела, проконсультируйтесь со специалистом или поэкспериментируйте; в22.1.
2. Используйте питег1с !!т!)з для определения свойств встроенных типов; 022.2. 3. Специализируйте литег!с !!т!Ьг для скалярных типов, определяемых пользователем; в22.2. 4. Для математических вычислений, в которых быстродействие важнее гибкости по отношению к типам и операциям, используйте га!аггау; в22.4. 5. Операции над частью массивов выражайте с помощью срезов, а не с помощью циклов; в22.4.6 .
б. Для достижения эффективности (избавления от временных объектов-массивов) применяйте технику композиции нескольких операций в единую функцию; 522.4.7. 7. Для комплексной арифметики применяйте юг!:: сотр!ех; 022.5. 8. Можно с помощью оператора гурег!еУперенастроить старый код, применяющий класс сотр!ех, на работу с шаблоном юг!: г сотр!ех; в22.5. 9. Рассмотрите возможность применения алгоритмов ассити!аге(), 1плег ргог!исг(),рагг1а! хит() наг!засел! ИЩегепсе() передтем, как писать циклы вычислений по значениям элементов последовательностей„в22.6. 10.
Отдавайте предпочтению классу случайных чисел с конкретным распределением непосредственному вызову функции гапг!(); в22.7. 11. Убедитесь, что ваши случайные числа действительно случайны; В22.7. 22.9. Упражнения 807 22.9. Упражнения 1. 2. 3.
4. 5. 6. 8. 9. 10. 11. 12. 13. 14. 15. (*!.5) Напишите функцию, которая ведет себя как арр!у(] из 922.4.3, но не является функцией-членом и принимает в качестве аргумента объекты функ- циональных классов. (*1.5) Напишите функцию, которая ведет себя как арр!у(] из 922.4.3, но не является функцией-членом, принимает в качестве аргумента объекты функ- циональных классов и изменяет аргумент типа «а!а««ау. (*2) Завершите Х!!се Яег (922.4.5). Будьте особо внимательны, определяя де- структор. (*1.5) Перепишите программу из 917.4.1.3, применив ассюиа!иге() .
(*2) Реализуйте операции ввода/вывода «и» для «а!аггау. Реализуйте функцию яег а««ау( ], которая создает массив «а!а««ау по размеру, задаваемо- му при вводе. (*2.5) Определите и реализуйте трехмерную матрицу с подходящими опера- циями. (*2.5) Определите и реализуйте и-мерную матрицу с подходящими операция- ми. (*2.5) Реализуйте класс, подобный «а!а««ау. Определите для него операции * и ь, Сравните его производительность с таковой для «а!а««ау из стандартной библиотеки. Подсказка: вычисляйте выражение х=О.
5* (х+у] ех для разных размеров векторов х, у и а ('3) Реализуйте массив Рогг аггау в стиле языка Гопгап, где индексы начина- ются с 1, а не с иуля. (*3) Реализуйте Маитх, используя для представления элементов «есгог<«ес- гог<(7оиЫе» (а не указатель на «а!аггау). (*2.5) Используя композицию операций в функции (922.4.7), реализуйте эф- фективную многомерную индексацию операцией [].
Например, «![х], «2[х1 [у], «2[х1, «З[х] [у] [х], «З[х] [у] и «З[х] должны порождать соответ- ствующие элементы и подмассивы на основе простого вычисления индекса. (*2) Обобщите идею из программы э22.7 в виде функции, которая получив в виде аргумента генератор случайных чисел, вывела бы графическое изобра- жение их распределения, которое послужило бы грубой оценкой корректно- сти генератора.
(*1) Если и имеет тип !иг, каково распределение (гоаб!е(гаиг7(]] (Х4%27 МАХ] *и? ("2.5) Выведите на экран точки внутри квадратной области. Пары координат точек должны вычисляться генератором Иаиг((]У], где Ж вЂ” число пикселов вдоль соответствующей стороны квадрата вывода. Что получающаяся карти- на может сказать вам о распределении случайных чисел генератором Еlгаи4? ("2) Реализуйте генератор Югаи4, дающий нормальное распределение случай- ных чисел. Часть 1Ч Проектирование с использованием С++ Здесь представлены возможности языка Сч-ч- в более широком плане разработки программного обеспечения.