Почему Cmath Pow дает неточные ответы? - PullRequest
0 голосов
/ 05 ноября 2018

В C ++ 11:

pow(1061,6);   // = 1426567426713180416

Проверьте последние 3 цифры. Я точно знаю, что результат неверный, потому что 1061 ^ 6 = 1426567426713180361.

Но этот другой метод делает это правильно:

long a =1;    
for(int i=0; i<6 ; i++){ a*=1061; }
cout << a;  // = 1426567426713180361

Pow включен в Cmath.

Если кто-нибудь знает, я хотел бы знать, почему оба результата не равны.

Ответы [ 3 ]

0 голосов
/ 05 ноября 2018

std::pow работает на double с. Он не сохраняет точность результирующего числа для таких больших целых значений, как это делает целочисленная арифметика.

0 голосов
/ 05 ноября 2018

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

Мы можем увидеть это легче, используя тот факт, что сужающиеся преобразования плохо сформированы при равномерной инициализации. Используя результаты, которые вы хотите, мы видим, что:

double d2{1426567426713180361};

- это сужающееся преобразование ( живой крестик )

error: constant expression evaluates to 9007199254740993 which cannot be narrowed to type 'double' [-Wc++11-narrowing]
double d1{9007199254740993} ;
        ^~~~~~~~~~~~~~~~

, поскольку он не может быть точно представлен. Мы также можем видеть число из ранее также является сужением конверсии:

double d1{9007199254740993} ;

в то время как:

double d3{1426567426713180416};

нет.

0 голосов
/ 05 ноября 2018

pow использует double для своего выхода, который имеет приблизительно 16 десятичных знаков точности. 64-битный long, однако, имеет 19.

...