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

Точность GCC С++

Итак, я был на конкурсе компьютерных игр, и я заметил странную ошибку. pow (26,2) всегда вернет 675, а иногда и 674? хотя правильный ответ - 676. Подобные ошибки возникают также и в случае pow (26,3), pow (26,4) и т.д. После некоторой отладки после конкурса я считаю, что ответ имеет отношение к тому, что int округляется. Интересно, что эта ошибка до меня никогда не происходила. Компьютер, который я имел, запускал mingw на окнах 8. Версия GCC была довольно новой, например, через 2-3 месяца. Но я обнаружил, что если бы я включил флаг оптимизации o1/o2/o3 при такой ошибке, чудесным образом исчезнет. pow (26,2) всегда получал бы 676 aka правильный ответ Может ли кто-нибудь объяснить, почему?

#include <cmath> 
#include <iostream> 

using namespace std; 
int main() { 
    cout<<pow(26,2)<<endl; 
    cout<<int(pow(26,2))<<endl; 
}

Результаты с удвоениями странны.

double a=26; 
double b=2; 
cout<<int(pow(a,b))<<endl; #outputs 675 
cout<<int(pow(26.0,2.0))<<endl; # outputs 676 
cout<<int(pow(26*1.00,2*1.00))<<endl; # outputs 676
4b9b3361

Ответ 1

Функция pow работает с двумя значениями с плавающей запятой и может поднять один на другой. Это делается с помощью аппроксимирующего алгоритма, так как требуется, чтобы он обрабатывал значения от наименьшего до самого большого.

Поскольку это аппроксимирующий алгоритм, он иногда получает значение немного неправильно. В большинстве случаев это нормально. Однако, если вы заинтересованы в получении точного результата, не используйте его.

Я бы настоятельно советовал использовать его для целых чисел. И если второй операнд известен (2, в этом случае), тривиально заменить его на код, который делает это намного быстрее и возвращает правильное значение. Например:

int square(int x)
{
  return x * x;
}

Чтобы ответить на реальный вопрос: некоторые компиляторы могут заменять вызовы на pow другим кодом или же все это исключить, когда известны один или оба аргумента. Это объясняет, почему вы получаете разные результаты.