Читаем О чём не пишут в книгах по Delphi полностью

 if R1 = R2 then Label1.Caption:= 'Равно'

 else Label1.Caption:= 'He равно';

end;

Почему этот пример также выдаст Не равно, понять проще, чем в предыдущем случае. При R1 бесконечная дробь обрывается на 24-х разрядах, а при R2 — на 53-х. Таким образом, в дополнительных по сравнению с типом Single разрядах переменной R2 будут единицы. При дополнении значений нулями до 10-байтной точности мы получим разные числа, что и определяет результат сравнения. Это напоминает ситуацию, когда мы сравниваем 0,333 и 0,3333, приводя их к точности в пять знаков: числа 0,33300 и 0,33330 не равны.

Как и в предыдущем случае, замена 0,1 на 0,5 даст результат Равно.

<p>3.2.9. Вычитание в цикле</p>

Рассмотрим еще один пример, иллюстрирующий ситуацию, которая часто озадачивает начинающего программиста (листинг 3.12, пример Subtraction на компакт-диске).

Листинг 3.12. Накапливание ошибки при вычитании

procedure TForm1.Button1Click(Sender: TObject);

var

 R: Single;

 I: Integer;

begin

 R:= 1;

 for I:= 1 to 10 do R:= R — 0.1;

 Label1.Caption:= FloatToStr(R);

end;

В результате выполнения этого кода на экране появится -7.3015691270939E-8 вместо ожидаемого нуля. Объяснение этому достаточно очевидно, если вспомнить то, о чем мы говорили ранее. Число 0,1 не может быть передано точно ни в одном из вещественных типов, а при каждом вычислении происходит преобразование Single в Extended и обратно, причем последнее — с потерей точности. Эти потери приводят к тому, что мы получаем в результате не ноль, а "почти ноль".

<p>3.2.10. Неожиданная потеря точности</p>

Изменим в предыдущем примере тип переменной R с Single на Double. Значение, выводимое программой, станет 1.44327637948555E-16. Вполне логичный и предсказуемый результат, т. к. тип Double точнее, чем Single, и, следовательно, все вычисления имеют меньшую погрешность, мы просто обязаны получить более точный результат. Хотя, разумеется, абсолютная точность (т. е. ноль) для нас остается недостижимым идеалом.

А теперь — вопрос на засыпку. Изменится ли результат, если мы заменим Double на более точный Extended? Ответ не такой однозначный, каким его хотелось бы видеть. В принципе, после такой замены вы должны получить -6.7762635780344E-20. Но в некоторых случаях от замены Double на Extended результат не изменится, и вы снова получите 1.44327637948555Е-16. Это зависит от операционной системы и версии Delphi.

Все дело в использовании "неполноценного" Extended. При запуске программы любая система устанавливает такое управляющее слово FPU, чтобы Extended был полноценным. Но затем программа вызывает много разных функций Windows API. Какая-то (или какие-то) из этих многочисленных функций некорректно работают с управляющим словом, меняя его значение и не восстанавливая при выходе. Такая проблема встречается, в основном, в Windows 95 и старых версиях Windows 98. Также имеются сведения о том, что управляющее слово может "портиться" и в Windows NT, причем эффект наблюдался не сразу после установки системы, а лишь через некоторое время, после доустановки других программ. Проблема именно в некорректности поведения системных функций; значение управляющего слова, устанавливаемое системой при запуске программы, всегда одинаково. Таким образом, приходим к неутешительному выводу: к тем проблемам с вещественными числами, которые обусловлены особенностями их аппаратной реализации, добавляются еще и ошибки операционной системы. Правда, радует то, что в последнее время эти ошибки встречаются крайне редко — видимо, новые версии системы от них избавлены. Тем не менее полностью исключать такую возможность нельзя, особенно если ваша программа будет запускаться на старой технике с устаревшими системами. Чтобы приведенный пример всегда выдавал правильное значение -6.7762635780344E-20, достаточно поставить в начале нашей процедуры Set808 °CW(Get8087CW or $0100), и программа в любой системе будет устанавливать сопроцессор в режим максимальной точности.

Примечание

В версиях Delphi по 5-ю включительно, где отсутствует функция Get8087CW, можно использовать такую конструкцию: Set8087CW(Default8087CW). При этом следует учитывать, что она возвращает к начальному состоянию все флаги, а не только интересующий нас. Если это неприемлемо, управляющее слово придется изменять с помощью встроенного ассемблера.

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных