2013-03-14 6 views
0

Я хотел бы понять, почему этот код:Понимание двойной точности операций в C

double r,d,rc; 
scanf("%lf %lf", &r, &d); 
rc = (r * r) - (d/2) * (d/2); 
printf("%.2f\n", M_PI * rc); 

возвращает более точный результат, чем этот (без rc присваивания значения переменной):

double r,d,rc; 
scanf("%lf %lf", &r, &d); 
printf("%.2f\n", M_PI * (r * r) - (d/2) * (d/2)); 

Другой, связанный, вопрос: почему n * n лучше, чем pow(n,2)?

+2

Затем прочитайте это - http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html –

+2

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

+0

Результаты безусловно, точно одинаковы * точные *. Вопрос в том, какой из них более точен *. –

ответ

5

Первый пример кода вычисляет:

M_PI * ((r * r) - (d/2) * (d/2)); 

Второй вычисляет:

(M_PI * (r * r)) - (d/2) * (d/2); 

Вызов pow(n, 2) такое же, как n * n, на большинстве компиляторов. точно такой же сборка будет излучаться. Это связано с оптимизацией, называемой «снижение силы». Большинство реализаций pow() проверит, является ли показатель степени 2, и уменьшите этот случай до одного умножения. Неоптимизированная версия немного дороже, так как требует вызова функции и некоторого разветвления.

Обратите внимание, что M_PI не является частью стандарта C, так что вы можете использовать эквивалент, который компилируется в точно такой же код:

double M_PI = 4.0 * atan(1.0); 
0

Чтобы ответить на второй вопрос; pow предназначен для выполнения произвольных полномочий, но неудивительно, что существует более быстрый способ вычисления ответа при постоянной мощности. Однократное умножение выполняется быстро (только инструкция одного процессора), тогда как для вызова pow требуется служебная информация вызова функции (без учета оптимизации на данный момент) и итеративный алгоритм, который многократно умножается, пока не получит ответ. Когда вы можете увидеть математический ярлык, чтобы избежать таких вещей, вы его используете.