Анимация
JavaScript


Главная  Библионтека 

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 [ 60 ] 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85

Резюме

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

При написании исходного текста помните о необходимости максимальной ясности и однозначности, всегда говорите именно то, что вы хотите сказать. Используйте в качестве аргументов конструктора именованные переменные, чтобы избежать описанных здесь неприятностей и сделать ваш код более ясным, поддерживаемым и сопровождаемым.



Задача 30. Двойная точность -

вежливость программистов Сложность: 4

Нет, эта задача не об этике. А о том, что есть разные виды "плавающей точки". Давайте проверим, насколько хорошо вы разбираетесь в основных операциях с плавающей точкой в С и С++.

Вопрос для новичка

1. В чем заключается различие между float и double? Вопрос для профессионала

2. Пусть приведенная далее программа выполняется одну секунду (что достаточно необычно для современных настольных компьютеров).

int main О {

double X = 1е8; whileC X > О ) {

--х;

Как вы думаете, сколько времени будет выполняться этот код, если изменить dou-ble на float? Почему?

Решение

Два слова о float и double

1. В чем заключается различие между float и double?

Процитируем отрывок из стандарта С++:

Имеется три типа с плавающей точкой: float, double и long double. Тип double обеспечивает, как минимум, ту же точность, что и float, а тип long double - как минимум, ту же точность, что и doub 1е. Множество значений, которые принимает тип float, представляет собой подмножество значений типа double; а множество значений типа double является подмножеством значений типа long double. - [С++03, §3.9.1/8]

Как это определение, в особенности его последнее предложение, могут повлиять на ваши исходные тексты?

Колесо времени

2. Пусть приведенная далее программа выполняется одну секунду (что достаточно необычно для современных настольных компьютеров).

int main С) {

double X = leS;

whileC X > О ) {

Как вы думаете, сколько времени будет выполняться этот код, если изменить double на float? Почему?



Вероятно, новое время выполнения составит около одной секунды (в конкретных реализациях работа с 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 е не будет равен исходному значению). Такое поведение в С++ разрешено для совместимости с С и для удобства работы, но о нем не следует забывать при работе с числами с плавающей точкой.

Резюме

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

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

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



0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 [ 60 ] 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85