Подтвердить что ты не робот

Почему 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; код работает, но с пятью он не работает.

4b9b3361

Ответ 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() - зарезервировать последнее для того, где это необходимо! Однако имейте в виду риск переполнения.