Можно ли сократить имя функции, которое я использую повторно? - PullRequest
0 голосов
/ 23 января 2019

У меня есть длинная формула, например:

float a = sin(b)*cos(c)+sin(c+d)*sin(d)....

Есть ли способ использовать s вместо sin в C, чтобы сократить формулу, без , влияющим на время работы?

Ответы [ 3 ]

0 голосов
/ 23 января 2019

Существует как минимум три варианта использования s для sin:

Использовать макрос препроцессора:

#define s(x) (sin(x))
#define c(x) (cos(x))
float a = s(b)*c(c)+s(c+d)*c(d)....
#undef c
#undef s

Обратите внимание, что определения макросов немедленно удаляются с помощью #undef, чтобы они не влияли на последующий код. Кроме того, вы должны знать об основах подстановки макросов препроцессора, отмечая тот факт, что первый c в c(c) будет расширен, а второй c - нет, так как расширен только функциональный макрос c(x) где за c следует (.

Это решение не повлияет на время выполнения.

Использовать встроенную функцию:

static inline double s(double x) { return sin(x); }
static inline double c(double x) { return cos(x); }

При хорошем компиляторе это не повлияет на время выполнения, так как компилятор должен заменить вызов s или c прямым вызовом sin или cos, что будет иметь тот же результат, что и оригинальный код. К сожалению, в этом случае функция c будет конфликтовать с объектом c, который вы показываете в своем примере кода. Вам нужно будет изменить одно из имен.

Использовать указатели функций:

static double (* const s)(double) = sin;
static double (* const c)(double) = cos;

При хорошем компиляторе это также не повлияет на время выполнения, хотя я подозреваю, что несколько других компиляторов могут не оптимизировать код с использованием этого решения, чем предыдущее решение. И снова у вас будет конфликт имен с c. Обратите внимание, что использование указателей на функции создает прямой вызов функций sin и cos, минуя все макросы, которые для них могла бы определить реализация C. (Реализациям на C разрешено реализовывать библиотечные функции, используя как макросы, так и функции, и они могут делать это для поддержки оптимизаций или определенных функций. При хорошем качестве компилятора это обычно не представляет особой проблемы; оптимизация прямого вызова все же должна быть хорошей .)

0 голосов
/ 23 января 2019

Не делайте этого.

Математики сокращают тригонометрические функции до sin , cos , tan , sinh , cosh и tanh на протяжении многих лет.Несмотря на то, что математики (как и я) любят использовать свои любимые и часто своеобразные обозначения, так что набрасывают любую бумагу на несколько страниц, они стали довольно стандартными.Даже в LaTeX есть такие команды, как \sin, \cos и \tan.

Японцы увековечили сокращения при выпуске научных калькуляторов в 1970-х годах (сокращение может легко поместиться на кнопке), и Cстандартная библиотека приняла их.

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

Но если вы должны , тогда просто

static double(*const s)(double) = sin;

хватит.

0 голосов
/ 23 января 2019

если я использую define, влияет ли это на время выполнения?

define работает путем подстановки текста во время компиляции.Если вы #define s(x) sin(x), то препроцессор C перепишет все s(x) в sin(x) до того, как компилятор получит возможность взглянуть на него.

Кстати, этот вид низкоуровневого преобразования текстаименно поэтому define может быть опасно использовать для более сложных выражений.Например, одна классическая ловушка заключается в том, что если вы делаете что-то вроде #define times(x, y) x*y, то times(1+1,2) переписывает в 1+1*2, что дает 3 вместо ожидаемого 4.Для более сложных выражений, таких как, часто хорошей идеей является использование встроенных функций .

...