Бьерн Страуструп. Язык программирования С++. Специальное издание (2011) (1004033), страница 164
Текст из файла (страница 164)
Например, вот одна из возможных реализаций для Яоаг. (еи(р1а(е<> с!азз питейс !(т((я<Дои(> ( риЫ(с: гаайс солз( Ьоо( (з зрес(ай(ей = (гие( з(айс сопи ш( гайх = 2; й основание степени (в данном случае, двойки) иайс соля( т( 4181(з = 24( В количество (двоичных) цифр в мантиссе з(айс сопя( 1п( 418!(з10 = 6; й количество десятичных цифр в мантиссе з(айс сопя( Ьоо! (з гВВпей = (гие( яиайс сопя( Ьоо( (з (п(еяег =/а!зе( з(айс сопз1 Ьоо! (з ехас( = уа(зе( з(айсЯоа( т(п () глюи() (гешгп 1.17549435Е-ЗВЕ( ) з(айсЯоа( тах() (Ьго(г() (ге(игп 3.40282347Е+3ВР( ) з(айсЯоа( ерзйоп () алгол ( ) (ге(игп 1. 1920929ОŠ— 07Г( ) з(айсугоа( гоилй егюг() глгои () (ге(игп 0.5Г( ) з(айс3(оа( (п((л((у() йиою() (ге(игп У* некоторое значение */( ) з(айсЯоа( цше1 )чаМ() плюю() (ге(игп У* некоторое.
значение *У; ) з(айсЯоа( ЫВпайпВ )ча)ч () тягою() (гетгп У* некоторое значение */( ) з(айс ((оа(йелогт тш () плюю() (ге(игп яип (); ) з(айс сопя! ии т(л ехропел( = -1251 з(айс сопз( ш( тш ехролеп110 = -37; з(айс сола ии тах ехропеп( = +128( з(аис сопз( ш( тах ехропеп(10 = +38( ментального типа (символьных типов, типа Ьоо1, целых чисел и чисел с плавающей запятой), но не для таких типов, как юЫ, перечисления или библиотечные типы (например, сотр1ех<йоиЫе>). Для интегральных типов, таких как сйаг, интерес представляет небольшая часть информации.
Вот специализация иишег(с !1ш!п<сйаг> для реализации, в которой тип сйаг знаковый и содержит 8 бит: 778 Глава 22. Классы для математических вычислений я(а((с сопя( Ьоо( Ьаз (иу(п!(у = (гие( я(апс солт Ьоо( Ьаз ди!е( 1Ча!( = ете( з(апс сопи! Ьоо1 Ьая я!дпадпд )уал( = (гое( з(апс сопя(Яоа( ((епогт яЯе Ьаз ((епогт = ((епогт аЬзеп(1 У епит из <Ит1и> таис сопя( Ьоо( Ьаз ((епогт !от = 1а(яе; з(апс сопя( Ьоо1 И (ес559 = (гие; // отвечает 1ЕС-559 з(аис сопз1 Ьоо( (з Ьоип((е(( = (гис( таис сопя( Ьоо( (з то((и!о =1а1(е; Паис сопя( Ьоо( (горя = иие( з(апс сопя( Ьоо1 паулет Ье1оге = (гие( з(апс сопя( Иоа( гоип(( я(у!е гоип(( иу1е = гоип(( (о пеагез(1 ~У епит ия <Ит!и> )! Отметим, что т!и() — это самое маленькое положительное нормализованное число, а еря1оп — самое маленькое положительное число с плавающей запятой такое, что 1«ерИ1оп-1 больше нуля.
Определяя некоторый скалярный тип в духе встроенных типов, неплохо определить для него и подходящую специализацию питег(с Итйя. Например, если бы я написал тип Диас( для чисел с учетверенной точностью, нли если бы в реализации оказался тип 1опя 1опп, пользователь мог бы ожидать наличия специализации питенс Ит1й<ДиаА> или питег(с Ит!(я<1опя 1опя>. Теоретически можно представить себе специализацию питенс ать для пользовательского типа, имеющего мало общего с числами с плавающей запятой. Но в таких случаях лучше использовать обычные способы для представления свойств типа, а не городить специализацию питеис 1й(ийх со свойствами, отличными от стандартных. В питенс Ит1(я свойства чисел с плавающей запятой представляются с помощью встраиваемых функций.
Для интегральных же типов свойства должны представляться в форме, допускающей их использование в константных выражениях. Это значит, что они должны иметь инициализаторы внутри класса (5)ОА.6.2). Если вы для этого используете статические константные члены, а не перечисления, не забудьте определить эти статические члены. 22.2.1. Макросы для предельных значений От языка С язык С++ унаследовал макросы, описывающие свойства целых чисел. Они расположены в заголовочных файлах <сат!а> и <Ит1(я. Ь> и имеют имена вроде СНАЯ ВПи Е(тт МАХ. Аналогично для чисел с плавающей запятой в заголовочных файлах <своа(> и <!1оа(.1(> расположены макросы вроде РВЕ МЕР( ЕХР, гЕТ ВАР()( и ЕРВЕ МАХ Как всегда, применения макросов лучше избегать.
22.3. Стандартные математические функции Заголовочные файлы <ста(Ь> и <та(й. Ь> объявляют то, что принято называть «общепринятыми математическими функциями». 22.3. Стандартные математические функции 779 йоиЫе аЬз (йоиЫе) з йоиЫеуабз (йоиЫе); д абсолютное значение (не в С); то же, что)абзр // абсолютное значение йоиЫе се(1 (йоиЫе й); йоиЫеЯоог (йоиЫе й); д наименьшее целое, не меньшее й ,У наибольшее целое, не большее й //квадратный корень из й, (й не отрицательное) йоиЫе зцгз (йоиЫе й); йоиЫе рою (йоиЫе й, йоиЫе х); /Уй в степени х, (еггог если й==О и х<=О и тп) йоиЫе ров(йоиЫе й, 1л11); дйв степени( (не в С) йоиЫе соз (йоиЫе); йоиЫе Ыл (йоиЫе); йоиЫе тап (йоиЫе); д косинус // синус д тангенс йоиЫе асов (йоиЫе); д арккосинус йоиЫе агйп (йоиЫе); У арксинус йоиЫе агап (йоиЫе); д арктангенс йоиЫе азап2 (йоиЫе х, йоиЫе у); У а(ап(х/у) йоиЫе лпЬ (йоиЬ1е); йоиЫе сова (йоиЫе); йоиЫе гапЬ (йоиЫе); д гиперболический синус // гиперболический косинус д гиперболический тангенс йоиЫе ехр (йоиЫе); йоиЫе 1оО (йоиЫе й); йоиЫе 1оя10 (йоиЫе й); У экспонента, основание е д натуральный логарифм (й должно быть >О) /У десятичный логарифм йоиЫе той( (йоиЫе й, йоиЫе* р); д возврат дробной части й (целая часть в *р) йоиЫеугехр(йоиЫе й, (зм* р); д ищет х в (5 1) ау так что й = х розг(2у), д возвращает х и сохраняет у в ьр йоиЫе(той (йоиЫе й, йоиЫе т); // остаток от деления (знак как у й) йоиЫе Ыехр(йоиЫе й, 1лг!); дсГрозч(2,О го(й1'( ) елло = О; зцгг(-1) ( ЗУ(ЕГГПО==Е)>ОМ) СЕГГ «чЗОГГ() ЛОГ йв~твй/ОГ ПЕОаикв аГОитвлн'( д очистка старого состояния, инициирующего ошибку рою(питепс Етпз<йоиЫе>:: так(),2); з1 (еггпо == ЕИАХСЕ) сегг « "гези1( ог рою () зоо 1агде го гергезепз аз а йоиЫен; ) По историческим причинам некоторые математические функции объявляются в <сзгй11Ь>, а не в <стагЬ>: Кроме того, заголовочные файлы <сзиатЬ> и <глагЬ.
Ь> предоставляют варианты этих функций для аргументов типа 77оаг и 1опя йоиЫе. Для функций, результат которых в обшем случае неоднозначен — например пз1п() — возврашается ближайшее к нулю значение. Функция асов() возвращает неотрицательное значение. Когда возникают ошибки, еггло из <сеггио> принимает значение ЕВОМ в случае выхода аргумента из области определения функций, и значение ЕИА))(СŠ— в случае выхода результата за возможные пределы значений типа. Например: Глава 22. Классы для математических вычислений 780 и! абю (то р 1оп8 аЬл (!опв) ) 1опе !абв (1опя); УУ абсолютное значение УУ абсолютное значение (не в С) УУ абсолютное значение кмис! й!г ! (!тр!степ!акоп Ивбпвй диоб гет; ); лггис! Ы!г ! (1тр!степ!акоп ав!)пеа' дион гвт; ); а(г ! а!г (Ьм и, !пг а'); УУ деление и на К возвращает (чостное, остаток) ЫЫ ! И!г (!опв т( и, 1опе тг а); УУ деление и но й, (не в С) !Йг ! Ыгг (!оае (п! и, !опе Ьм й); УУ деление и но с( возвращает (чостнос, остаток) 22.4.
Векторная арифметика 22.4.1. Конструкторы класса зга!аггау Сам класс га1аггау и его вспомогательные средства определены в пространстве имен вЫ и представлены в заголовочном файле <га!аггау>: Часто в программах математические вычисления сводятся к относительно простой обработке одномерных массивов (векторов) чисел с плаваюшей запятой. Такие векторы, в частности, поддерживаются на аппаратном уровне для высокопроизволительных суперкомпьютеров, для них написано множество библиотек обшего назначения, и, кроме того, имеются их глубоко оптимизированные версии для специальных применений. Как следствие, стандартная библиотека языка С++ также предоставляет специальный векторный класс — га(штау — специально разработанный для быппрых численных операций над векторссии. Глядя на предоставляемые классом га1аггау средства, нужно помнить, что они представляют собой довольно низкоуровневые строительные блоки для высокопроизводительных вычислений.
В итоге, главным критерием проектирования была не простота их использования, а возможность эффективного применения на высокопроизводительных компьютерах в условиях агрессивной оптимизации. Если ваша цель— это гибкость и универсальность, а вовсе не особая эффективность, то вам лучше строить вычисления на основе контейнеров из глав 16 и 17, и не пытаться втиснуться в жесткие рамки простого, эффективного и намеренно традиционного вектора га1аггау. Кто-нибуль может сказать, что га1аггау следовало бы назвать гес!ог, поскольку он близок традиционному математическому вектору, а вес!ог (516.3) следовало бы назвать аггау, так как это скорее массив в обычном смысле. Но терминология развивалась в ином направлении: га1аггау — это специальный вектор, оптимизированный для серьезных математических вычислений; весгог — зто гибкий контейнер лля хранения и манипулирования объектами различных типов, а массивами (аггауз) принято называть низкоуровневые встроенные типы данных.
Тип га1аггау поддержан четырьмя подтипами, специфицируюшими подмножества ча1агаа: ° в!!се аггау и ля!!се аггау представляют понятие срезов (522.4.6, 822.4.8), ° тав!с аггау специфицирует подмножество путем маркировки элементов (з22.4.9), ° (па)гес! аггау содержит индексы необходимых элементов 622.4.10). ув1 22 4 Векторная арифметика !етр(а(е<с(авв Т> с1авв зИ:: ча(актау ( // внутреннее представление рибдс: ~рез(е! Т ча(ие (уре; // ча(оггау с з(лей==О /У и элементов со значением Т() /У п элементов со значением чо! У и элементов со значениями р(О), р(11, . //копия ч ча(аггау ( ); екрдсй ча1азтау (з(ге ! и ); ча(аггау(сопл( Ть ча(, Ыье ! и); ча(аггау(сопл( Т* р, Ысе 1 п) з ча(аггау(сопл! ча(аггауь ч) ) ча(аггау(сопя(з((се аггау<Т>ь); //см.
322.4б ча(аггау (сопя(8з(!се аггау<Т>ь ); // см. 822.4 8 ча(аггау(сопз(таза аггау<Т>ь); //см. 322.4.9 ча(аггау(сопл( !пз(!гес! аггау<Т>ь ); //см. 822.4.10 -ча(а1тау() ( // ... )) Данный набор конструкторов позволяет нам инициализировать ча(аггау, используя числовые массивы вспомогательных типов или отдельные значения. Например: //можно присвоить что-нибудь позже /У (000 элементов со значением)(оаг() ==О.Ог //2000 элементов со значением -! У ошибка: размер задан числом с плов. запятой // ч4 содержит чЗлбзе() элементов ча(аггау<з(оиЫе> чО; ча(аггау<((оа!> ч( (1000) з ча(аггау<Ы(> ч2 (-1, 2000); ча(ап ау<з(оиЫе> чЗ (100, 9.