Почему pow (n, 2) возвращает 24, когда n = 5, с моим компилятором и ОС?
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
int n,i,ele;
n=5;
ele=pow(n,2);
printf("%d",ele);
return 0;
}
Выходной сигнал 24
.
Я использую GNU/GCC в Code:: Blocks.
Что происходит?
Я знаю, что функция pow
возвращает a double
, но 25
соответствует типу int, поэтому почему этот код печатает 24
вместо 25
? Если n=4; n=6; n=3; n=2;
код работает, но с пятью он не работает.
Ответы
Ответ 1
Вот что может происходить здесь. Вы должны быть в состоянии подтвердить это, посмотрев на реализацию вашего компилятора функции pow
:
Предполагая, что у вас есть правильный # include, (все предыдущие ответы и комментарии об этом верны - не принимают файлы #include
как данно), прототипом стандартной функции pow
является следующее:
double pow(double, double);
и вы вызываете pow
следующим образом:
pow(5,2);
Функция pow
проходит через алгоритм (возможно, используя логарифмы), поэтому использует функции и значения с плавающей запятой для вычисления значения мощности.
Функция pow
не проходит через наивную "умножить значение x в сумме n раз", так как она также должна вычислять pow
с использованием дробных показателей, и вы не можете вычислить дробные полномочия таким образом.
Таким образом, более вероятно, что вычисление pow
с использованием параметров 5 и 2 привело к небольшой ошибке округления. Когда вы назначили int
, вы усекали дробное значение, давая 24.
Если вы используете целые числа, вы можете написать свою собственную "intpow" или аналогичную функцию, которая просто умножает значение необходимое количество раз. Преимущества этого:
-
Вы не столкнетесь с ситуацией, когда вы можете получить тонкие ошибки округления с помощью pow
.
-
Функция intpow
скорее всего будет работать быстрее, чем эквивалентный вызов pow
.
Ответ 2
Вы хотите получить результат от функции, предназначенной для удвоения.
Возможно, вы должны использовать
ele=(int)(0.5 + pow(n,2));
/* ^ ^ */
/* casting and rounding */
Ответ 3
Если вы не #include <math.h>
, то компилятор не знает типы аргументов pow()
, которые являются как double
not int
, поэтому вы получаете результат undefined. Вы получаете 24, я получаю 16418.
Ответ 4
Когда вы используете pow с переменными, его результат double
. Назначение int
обрезает его.
Таким образом, вы можете избежать этой ошибки, назначив результат переменной pow
to double
или float
.
Итак, в основном
Это означает exp(log(x) * y)
, который приведет к результату, который не точно совпадает с x^y
- почти приближенным значением в качестве значения с плавающей запятой. Так, например, 5^2
станет 24.9999996
или 25.00002
Ответ 5
Арифметика с плавающей точкой не является точной.
Хотя небольшие значения могут быть добавлены и вычтены точно, функция pow()
обычно работает путем умножения логарифмов, поэтому даже если входы являются точными, результат не будет. Присвоение int
всегда усекает, поэтому, если неточность отрицательная, вы получите 24, а не 25.
Мораль этой истории состоит в том, чтобы использовать целые операции над целыми числами и быть подозрительными к функциям <math.h>
, когда фактические аргументы должны быть продвинуты или усечены. К сожалению, GCC не предупреждает, если вы не добавили -Wfloat-conversion
(это не в -Wall -Wextra
, возможно, потому что есть много случаев, когда такое преобразование ожидается и нужно).
Для целых степеней всегда более безопасно и быстрее использовать умножение (деление, если отрицательное), а не pow()
- зарезервировать последнее для того, где это необходимо! Однако имейте в виду риск переполнения.