это один печатает 100:C: у меня разные результаты с pow (10,2) и pow (10, j), j = 2;
int j=2;
int i= pow(10,2);
printf("%d\n", i);
и этот гравюр 99:
int j=2;
int i= pow(10,j);
printf("%d\n", i);
почему?
это один печатает 100:C: у меня разные результаты с pow (10,2) и pow (10, j), j = 2;
int j=2;
int i= pow(10,2);
printf("%d\n", i);
и этот гравюр 99:
int j=2;
int i= pow(10,j);
printf("%d\n", i);
почему?
что происходит в том, что у вас есть реализация C, чья стандартная библиотека имеет очень низкую реализацию качества pow
, который возвращает неточные результаты, даже если точный результат представлен в типе (double
). Вызов pow(10,2)
, похоже, создает значение чуть ниже 100.0
, которое при округлении до целого числа дает 99. Причина, по которой вы не видите это, когда аргументы постоянны, заключается в том, что компилятор взял на себя смелость оптимизировать вызов alltogether и замените его постоянным 100 в compiletime.
Если вы намерены выполнять целые полномочия, не используйте функцию pow
. Напишите правильную целочисленную функцию мощности или когда показатель степени известен, просто напишите умножение напрямую.
Да, даже если библиотека pow вычисляет точный результат, правильно округленный, полагаясь на каждое целое число, которое будет представлено точно в double, является хрупким. Я жду аванса 64 бит int, чтобы спросить, почему pow (11,18) неправильно вычисляется. –
На практике это безопасно с этой точки зрения. «int» никогда не изменится в практических (не-DSP) реализациях из-за многих проблем, связанных с неожиданными эффектами целочисленного продвижения, проблемами исключения одного шага размера от стандартных типов и просто простой совместимостью. –
В первом случае я подозреваю, что компилятор оптимизировал значение до 10*10
без фактического вызова pow
(составители действительно делают это). Во втором случае похоже, что у вас ошибка округления с плавающей запятой. В результате почти 100, но не совсем, и неявный литой до int
усекает его.
Функция pow
работает на double
, а не int
.
В целом (но не всегда), когда вы конвертируете двойные числа в целые числа, вы вызываете round()
. Например:
int i = (int) round(pow(10,j));
Если ваша библиотека C не имеет этого, вы можете эмулировать:
#define round(x) floor((x)+0.5)
pow
возвращается double
и поэтому, если результат не совсем 100
, но немного меньше, чем это усечение, когда конвертируя в int
, и вы получите результат 99
, который вы видите. Было бы интересно посмотреть, как выглядят результаты для переменной double
и %f
.
Причина, по которой вы не увидите ее при использовании литералов, вызвана constant folding, что вызовет необходимость оптимизации и замену на pow
. Мы можем видеть версию, которая использует константы, когда мы формируем сборку не вызов pow
не сделал это просто перемещает конечный результат 100
(увидеть его live):
movl $100, -4(%rbp)
в то время как версия второго варианта фактически вызывает pow
(увидеть live):
call pow
Я получил 100 оба раза с двойным. –
Какой компилятор вы используете и на какой системе? –
Оба 100 для меня. –
Мое предположение - это целочисленное усечение двойного результата, было бы интересно посмотреть, как выглядит ''% f ''. –