производительность — как определить макрос pow2 в Stack Overflow

Я хочу получить определение для pow2C следующим образом. Но мой компилятор показывает, что (__tmpDouble__) уже определено. Пожалуйста, помогите мне определить это.

#ifndef pow2C
double __tmpDouble__;
#define pow2C(a) ((__tmpDouble__=(a))*(__tmpDouble__))
#endif

.
.
.

inline double calculateDistance(double *x, double *y, int NDims)
{
double d = 0;
for (int i = 0; i < NDims; i++)
// it is faster to calculate the difference once
d += pow2C(x[i] - y[i]);
return sqrt(d);
}

-1

Решение

Я хочу вычислить x [i] -y [i] только один раз, сохранить его в переменной и использовать.

Вы уже рассчитываете только один раз. Это все бессмысленно.

Если вы все еще настаиваете, то ошибка, которую вы называете не существует в этом коде.

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

#include <iostream>
#include <cmath>
#include <array>

#ifndef pow2C
double __tmpDouble__;
#define pow2C(a) ((__tmpDouble__=(a))*(__tmpDouble__))
#endifinline double calculateDistance(double *x, double *y, int NDims)
{
double d = 0;
for (int i = 0; i < NDims; i++)
// it is faster to calculate the difference once
d += pow2C(x[i] - y[i]);
return sqrt(d);
}

int main()
{
const size_t NUM_DIMS = 3;
std::array<double, NUM_DIMS> x{{5.0, 6.0, 7.0}};
std::array<double, NUM_DIMS> y{{1.2, 1.5, 9.0}};

std::cout << "Distance between x and y is: " << calculateDistance(&x[0], &y[0], NUM_DIMS) << '\n';
}

// g++-4.8 -std=c++11 -Wall -pedantic -pthread main.cpp && ./a.out
// main.cpp: In function 'double calculateDistance(double*, double*, int)':
// main.cpp:16:31: warning: operation on '__tmpDouble__' may be undefined [-Wsequence-point]
//         d += pow2C(x[i] - y[i]);
//                                ^
// Distance between x and y is: 6.22013

Итак, действительно, мы вернулись к не делай этого.


Если вы все еще отчаянно пытаетесь избежать оценки x[i] - y[i] дважды:

inline double calculateDistance(double* x, double* y, int NDims)
{
double d = 0;
for (int i = 0; i < NDims; i++) {
const double diff = x[i] - y[i];
d += diff * diff;
}

return sqrt(d);
}

Вы можете передать работу умножения другому inline функция полезности, если хотите, но здесь нет необходимости в макросе.

2

Другие решения

Если вы настаиваете на написании макроса, используйте другое имя для переменной. Но твой макрос очень ужасен. Во-первых, это не потокобезопасно в отношении одновременных вызовов, поскольку потоки будут обращаться к одной и той же временной переменной. Также, самый макросы вообще очень злые (есть немного исключения хотя).

Тем не менее, то же самое (также с точки зрения производительности) может быть достигнуто гораздо проще (даже с поддержкой float и другие типы с operator* с шаблоном функции:

template <typename T>
T square(const T &v) {
return v * v;
}

Если вы хотите макрос, то #define pow2C square (знак сарказма).

8

Это ужасный способ определения макроса! Вы никогда не должны вводить переменные как часть расчета. Вместо этого попробуйте это:

#define pow2C(a) ((a) * (a))

Однако макросы ужасны для такого рода вычислений, так как они могут быть неэффективными и вызывать нежелательные побочные эффекты. Например, если вы закодируете код, он расширится до:

 (x[i] - y[i]) * (x[i] - y[i])

Где вы сделали вычитание дважды!

Вместо этого используйте шаблоны C ++:

template<class T>
T pow2C(const T &value)
{
return value * value;
}

Теперь вы только один раз будете делать вычитание!

5
По вопросам рекламы [email protected]