所以我有一个奇怪的问题,GNU GCC(C / C ++)宏定义如下:
#define PI 3.14159265359
#define DEG_TO_RAD(a) (a * PI / 180.0)
#define ARCSEC_TO_DEG(a) (a / 3600.0)
#define ARCSEC_TO_RAD(a) DEG_TO_RAD( ARCSEC_TO_DEG( a ) )
正如您所知,宏只是将弧的秒数转换为弧度。但是,根据宏的应用位置,我得到了不同的结果:
double xi2 = ARCSEC_TO_RAD( 2306.2181 * c + 0.30188 * c2 + 0.017998 * c3);
double xi = 2306.2181 * c + 0.30188 * c2 + 0.017998 * c3;
printf("c = %.10f; xi = %.10f = %.10f = %.10f; ",
c, xi, ARCSEC_TO_RAD(xi), xi2);
输出:
c = 0.1899931554; xi = 438.1766743152 = 0.0021243405 = 7.6476237313;
哪里是愚蠢的错误......?
答案 0 :(得分:3)
我强烈建议你使用函数(也许是inline)而不是MACROS, 但如果由于某种原因你不能解决问题,那么解决方法可能是在收到的参数中添加括号:
#define PI 3.14159265359
#define DEG_TO_RAD(a) ((a) * PI / 180.0)
#define ARCSEC_TO_DEG(a) ((a) / 3600.0)
#define ARCSEC_TO_RAD(a) DEG_TO_RAD( ARCSEC_TO_DEG( (a) ) )
//In the lastone () is not necessary but it a good prectice always adding parenthesis to macro args
这可以防止在扩展宏时出现与运算符优先级相关的错误。
答案 1 :(得分:2)
一步一步走,
ARCSEC_TO_RAD( 2306.2181 * c + 0.30188 * c2 + 0.017998 * c3);
将扩展为
DEG_TO_RAD( ARCSEC_TO_DEG(2306.2181 * c + 0.30188 * c2 + 0.017998 * c3))
DEG_TO_RAD( (2306.2181 * c + 0.30188 * c2 + 0.017998 * c3 / 3600.0))
((2306.2181 * c + 0.30188 * c2 + 0.017998 * c3 / 3600.0) * P* / 180.0)
现在常规操作顺序就在这里,因此2306.2181 * c + 0.30188 * c2 + 0.017998 * c3
将 不 除以3600.只有0.017998 * c3
会。旧学校C解决方案是在宏观替换周围放置括号。
现代的C和C ++解决方案是使用功能。 inline
函数need to to meet ODR,但编译器可能会自行决定是否应该内联扩展函数。
这个问题标记为C ++,所以这里是C ++解决方案:
#include <iostream>
constexpr double PI = 3.14159265359;
/* or
#include <cmath>
const double PI = std::acos(-1);
but I'm not certain you can properly constexpr this */
double DEG_TO_RAD(double a)
{
return a * PI / 180.0;
}
double ARCSEC_TO_DEG(double a)
{
return a / 3600.0;
}
double ARCSEC_TO_RAD(double a)
{
return DEG_TO_RAD( ARCSEC_TO_DEG( a ) );
}
int main ()
{
double c = 10;
double c2 = 20;
double c3 = 30;
std::cout << DEG_TO_RAD(2306.2181 * c + 0.30188 * c2 + 0.017998 * c3) << std::endl;
}
在C ++ 11或更新版本中,constexpr
can be added使这些以前的宏编译时常量应该是必要的。