Стив Саммит. Язык си в вопросах и ответах.Операции с плавающей точкой.
Ответы на вопросы разбиты по темам:
4. Выражения
5. ANSI C
7. Списки аргументов переменной длины.
8. Булевы выражения и переменные.
9. Структуры, перечисления и объединения.
10. Декларации.
13. Lint.
14. Стиль.
15. Операции с плавающей точкой.
16. Интерфейс с операционной системой.
17. Разное (Пребразование Fortran -> C , грамматики для YACC и т.п.)
Операции с плавающей точкой.
15.1 У меня операции с плавающей точкой выполняются странно, и на разных машинах получаются различные результаты.
О: Сначала убедитесь, что подключен головной файл <math.h> и правильно объявлены другие функции, возвращающие тип double.
Если дело не в этом, вспомните, что большинство компьютеров используют форматы с плавающей точкой, которые хотя и похоже, но вовсе не идеально имитируют операции с действительными числами. Потеря значимости, накопление ошибок и другие свойственные ЭВМ особенности вычислений могут быть весьма болезненными.
Не нужно предполагать, что результаты операций с плавающей точкой будут точными, в особенности не стоит проверять на равенство два числа с плавающей точкой. (Следует избегать любых ненужных случайных факторов.)
Все эти проблемы одинаково свойственны как С, так и другим языкам программирования. Семантика операций с плавающей точкой определяется обычно так, «как это выполняет процессор»; иначе компилятор вынужден бы был заниматься непомерно дорогостоящей эмуляцией «правильной» модели вычислений.
В этих вопросах и ответах нет возможности даже бегло перечислить все затруднения при вычислениях с плавающей точкой и способы их преодоления. Хорошая книга по программированию должна содержать введение в эту область.
Смотри: EoPS Разд. 6 c. 115-8.
15.2 Я пытаюсь проделать кое-какие вычисления, связанные с тригонометрией, включаю <math.h>, но все равно получаю сообщение: «undefined: _sin» во время компиляции.
О: Убедитесь в том, что компоновщику известна библиотека, в которой собраны математические функции. Например, в операционной системе UNIX часто необходим ключ -lm в самом конце командной строки. См. также вопрос 12.14.
15.3 Почему в языке С нет оператора возведения в степень?
О: Потому что немногие процессоры имеют такую инструкцию. Вместо этого можно, включив головной файл <math.h>, использовать функцию pow(), хотя часто при небольших целых порядках явное умножение предпочтительней.
Смотри: ANSI Разд. 4.5.5.1 .
15.4 Как округлять числа?
А: Вот самый простой и честный способ:
(int)(x + 0.5)
Хотя для отрицательных чисел это не годится.
15.5 Как выявить специальное значение IEEE NaN и другие специальные значения?
О: Многие компиляторы с высококачественной реализацией стандарта IEEE операций с плавающей точкой обеспечивают возможность (например, макрос isnan()) явной работы с такими значениями, а Numerical C Extensions Group (NCEG) занимается стандартизацией таких средств. Примером грубого, но обычно эффектиного способа проверки на NaN служит макрос
#define isnan(x) ((x) != (x))
хотя не знающие об IEEE компиляторы могут выбросить проверку в процессе оптимизации.
15.6 У меня проблемы с компилятором Turbo C. Программа аварийно завершается, выдавая нечто вроде «floating point formats not linked.»
О: Некоторые компиляторы для мини-эвм, включая Turbo C (а также компилятор Денниса Ритчи для PDP-11), не включают поддержку операций с плавающей точкой, когда им кажется, что это не понадобится. В особенности это касается версий printf и scanf, когда для экономии места не включается поддержка %e, %f, и %g. Бывает так, что эвристической процедуры Turbo C, которая определяет — использует программа операции с плавающей точкой или нет, оказывается недостаточно, и программист должен лишний раз вызвать функцию, использующую операции с плавающей точкой, чтобы заставить компилятор включить поддержку таких операций.