Программирование >>  Обобщенные обратные вызовы 

1 ... 57 58 59 [ 60 ] 61 62 63 ... 84


Вероятно, новое время выполнения составит около одной секунды (в конкретных реализациях работа с float может быть немного быстрее, такой же по скорости, или немного медленнее, чем работа с double), либо выполнение никогда не прекратится - в зависимости от того, может ли тип float точно представить все целые значения от О до 1е8 включительно или нет.

Приведенная цитата из стандарта означает, что вполне возможны значения, п ре дета-вимые типом double, которые не в состоянии представить тип float. В частности, на некоторых распространенных платформах и компиляторах double может точно представить все целые числа из диап;иона от О до 1е8. но тип float на эго не способен.

Что происходит, если float не в состоянии точно представить все целые числа от О до 1е8? Тогда измененная програм.ма, приступив к уменьшению счетчика, в конечном счете достигнет значения N, которое не может быть точно представлено и для которого выполняется равенство i\-l=--,\ (из-за недостаточной точности представления чисел с плавающей точкой)... и произойдет зацикливание на этом значении, пока не закончится электроэнергия, не произойдет сбой операционной системы (что для ряда операционных систем - обычное дело). Солнце не превратится в пульсар и не сожжет все внутренние планеты. Вселенная не погибнет от тепловой смерти... - словом, что произойдет раньше.5

О суживающем преобразовании типов

Некоторые читатели могут удивиться: Какие могут быть проблемы - если, конечно, не считать приближение конца света? Константа 1е8 имеет тип doubl е. При замене double на float программа не должна компилироваться из-за суживающего преобразования типов, не так ли? Ну что ж, давайте привычно процитируем еще одно место из стандарта:

rvalue типа с плавающей точкой может быть преобразовано в rvalue другого типа с плавающей точкой. Если исходное значение точно представимо целевым типом, то результат преобразования является точным представлением. Если исходное значение оказывается между двумя соседними целевыми значениями, то результат преобразования является одним из этих значений и зависит от конкретной реализации. В противном случае поведение не определено. - [С-Ы-ОЗ] §4.8/1

Это означает, что константа типа doubl е может неявно быть преобразована в константу типа float, даже если при этом происходит потеря точности (т.е. части данных, так что результат обратного преобразования к типу doubl е не будет равен исходному значению). Такое поведение в С++ разрешено для совместимости с С и для удобства работы, но о нем не следует забывать при работе с числами с плавающей точкой.

Резюме

Вычисления с плавающей точкой сложны, трудны и почти всегда - неочевидны. Я бы сказал -- с известной долей самомнения - что все программисты делятся на три группы: те, кто знают, что они не понимают вычисления с плавающей точкой (и они правы); те, кто думают, что они понимают их (но они ошибаются); и тс немногие эксперты, которые совсем не уверены в том, что когда-либо полностью сумеют разобраться в вычислениях с плавающей точкой (и это мудро).

Вообще-то толку от такой программы - ноль, так что оиа просто увеличивает энтропию Вселенной, приближая ее тепловую смерть и ничего не давая взамен. Так что никогда не пишите такие экологически опасные программы!

Кстати, любая работа человека или машины приводит к тому же эффекту и ускоряет наступление конца света. Этот аргумент может вам пригодиться, когда ваш работодатель предложит вам поработать сверхурочно...



> Рекомендация

Запомните, что вычисления с плавающей точкой - таинственная и странная вещь. Будьте внимательны при использовании чисел с плавающей точкой и избегайте преобразования типов с плавающей точкой. Почти все, что люди (как они думают) знают об арифметике, оказывается не верно применительно к вычислениям с плавающей точкой.

Качественный компилятор предупредит вас, если вы попытаетесь сделать что-то с неопределенным поведением, а именно-- поместить в переменную float величину типа double, которая меньше минимального или больше максимального представи-мого типом float значения. По-настоящему хороший компилятор позволяет включить предупреждения о попытках сделать что-то, что разрешено и определено в стандарте, но может вызвать потерю информации, а именно - поместить величину типа double в переменную типа float, находящуюся между минимальным и максимальным представимыми типом float значениями, но не имеющую точного представления в .этом типе.

Словом, будьте внимательны, избегайте полагаться на преобразования типов с плавающей точкой и не забудьте включить всю диагностику, на которую только способен ваш компилятор, - тогда у вас есть хоть какой-то шанс перебраться вброд через мутные воды арифметики с плавающей точкой.



Задача 31. Сумеречное состояние... кода Сложность: 4

Иногда жизнь заставляет нас заниматься отладкой в ситуациях, которые иначе как таинственными, назвать сложно. Попробуйте свои силы и в этом. Сможете ли вы объяснить причину возникающих проблем?

Вопрос ДЛЯ профессионала 1. Один программист написал следующий код. - file biology.h -

... необходимые заголовочные файлы и прочее ...

class Animal { public:

функции, работающие с данным объектом:

virtual int Eat ( int ) { /*...*/ } virtual int Excrete ( int ) { /*...*/ } vi rtual int Sleep ( int ) { /*...*/ } virtual int wake ( int ) { /*...*/ }

специально для животных, которые уже были в браке, и иногда не терпят своих бывших супругов:

int EatEx С Animal* а ) { /*...*/ }

int ExcreteEx ( Animal* a ) { /*...*/ }

int SleepEx ( Animal* a ) { /*...*/ }

int WakeEx ( Animal* a ) { /*...*/ }

конкретные классы

class cat : public Animal { /*...*/ } class Dog : public Animal { /*...*/ } class weevil : public Animal { /*...*/ } ... прочие животные ...

Удобные, хотя и излишние, вспомогательные функции

int Eat ( Animal* а ) { return a->Eat( 1 ); } int ExcreteC Animal* a ) { return a->Excrete( 1 ); } int Sieep ( Animal * a ) { return a->Sleep( 1 ); } int Wake ( Animal* a ) { return a->Wake( 1 ); }

К сожалению, этот исходный текст не компилируется. Компилятор отклоняет определение как минимум одной из ...Ех-функций с сообщением о том, что функция

уже определена.

Чтобы обойти эту ошибку компиляции, программист закомментировал ...Ех-функции, после чего скомпилировал программу и начал тестирование. К сожалению, функция-член Animal::sleep не всегда работала корректно; однако когда программист вызывал ее непосредственно, все было в порядке. Однако при попытке вызвать се из функции-оболочки sleep, в которой не выполняется никаких иных действий, кроме вызова функции-члена, иногда не происходило ничего... не всегда, но такое случалось. И наконец, когда программист попытался разобраться в проблеме при помощи отладчика (или карты символов, сгенерированной компоновщиком), то он вообще не нашел и следа кода Animal :: Sleep.



1 ... 57 58 59 [ 60 ] 61 62 63 ... 84

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика