在 C++ 中说 "promote everything to floating before calculation" 的确定性方式
Deterministic way of saying "promote everything to floating before calculation" in C++
鉴于我更愿意在我的程序中将数字保留为 int
s 或任何整数,用这些数字的浮点等价物进行任意算术运算的最方便的方法是什么?
说,我有
int a,b,c,d;
double x;
我想写
x=a/b/c/d+c/d+a;
通过将转换放在已解析的运算符树叶子中的任何地方,而不会使表达式变得一团糟,例如
x=(double)a/b/c/d+(double)c/d+a;
C 风格的宏是否可行(是否递归)?应该用新的 class 和重载的运算符来完成吗?
x=a/b/c/d+c/d+a;
这是一个相当复杂的表达式。最好给它起个名字:
double complex_expression(double a, double b, double c, double d) {
return a/b/c/d+c/d+a;
}
现在,当您使用整数参数调用它时,由于参数的类型为 double
,因此使用通常的算术转换将参数转换为 double
:
int a,b,c,d;
// Init them somehow
double x = complex_expression(a,b,c,d);
使用 C++11 lambda ...
int a,b,c,d;
// Init them somehow
double x = [](double a, double b, double c, double d) {
return a/b/c/d+c/d+a; }(a,b,c,d);
... 有效,但 IMO 看起来有点笨拙。
稍微好一点?
double x = [a = (double)a, b = (double)b, c = (double)c, d = (double) d] {
return a/b/c/d+c/d+a; }();
哦,如果你想要一些宏观的乐趣:
#define SPLICE_2(l,r) l##r
#define SPLICE_1(l,r) SPLICE_2(l,r)
#define SPLICE(l,r) SPLICE_1(l,r)
#define TREAT_AS(type, name) name = static_cast<type>(name)
#define TREAT_ALL_AS_HELPER_0(type)
#define TREAT_ALL_AS_HELPER_1(type, name) TREAT_AS(type, name)
#define TREAT_ALL_AS_HELPER_2(type, name, ...) TREAT_AS(type, name), TREAT_ALL_AS_HELPER_1(type, __VA_ARGS__)
#define TREAT_ALL_AS_HELPER_3(type, name, ...) TREAT_AS(type, name), TREAT_ALL_AS_HELPER_2(type, __VA_ARGS__)
#define TREAT_ALL_AS_HELPER_4(type, name, ...) TREAT_AS(type, name), TREAT_ALL_AS_HELPER_3(type, __VA_ARGS__)
#define TREAT_ALL_AS_HELPER_5(type, name, ...) TREAT_AS(type, name), TREAT_ALL_AS_HELPER_4(type, __VA_ARGS__)
// expand as you will
#define TREAT_ALL_AS(type, count, ...) SPLICE(TREAT_ALL_AS_HELPER_, count)(type, __VA_ARGS__)
现在用作
double x = [TREAT_ALL_AS(double, 4, a, b, c, d)] {
return a/b/c/d+c/d+a; }();
你也可以automatically count the number of variadic macro arguments.
但老实说,IMO 最好只编写一个命名函数。
鉴于我更愿意在我的程序中将数字保留为 int
s 或任何整数,用这些数字的浮点等价物进行任意算术运算的最方便的方法是什么?
说,我有
int a,b,c,d;
double x;
我想写
x=a/b/c/d+c/d+a;
通过将转换放在已解析的运算符树叶子中的任何地方,而不会使表达式变得一团糟,例如
x=(double)a/b/c/d+(double)c/d+a;
C 风格的宏是否可行(是否递归)?应该用新的 class 和重载的运算符来完成吗?
x=a/b/c/d+c/d+a;
这是一个相当复杂的表达式。最好给它起个名字:
double complex_expression(double a, double b, double c, double d) {
return a/b/c/d+c/d+a;
}
现在,当您使用整数参数调用它时,由于参数的类型为 double
,因此使用通常的算术转换将参数转换为 double
:
int a,b,c,d;
// Init them somehow
double x = complex_expression(a,b,c,d);
使用 C++11 lambda ...
int a,b,c,d;
// Init them somehow
double x = [](double a, double b, double c, double d) {
return a/b/c/d+c/d+a; }(a,b,c,d);
... 有效,但 IMO 看起来有点笨拙。
稍微好一点?
double x = [a = (double)a, b = (double)b, c = (double)c, d = (double) d] {
return a/b/c/d+c/d+a; }();
哦,如果你想要一些宏观的乐趣:
#define SPLICE_2(l,r) l##r
#define SPLICE_1(l,r) SPLICE_2(l,r)
#define SPLICE(l,r) SPLICE_1(l,r)
#define TREAT_AS(type, name) name = static_cast<type>(name)
#define TREAT_ALL_AS_HELPER_0(type)
#define TREAT_ALL_AS_HELPER_1(type, name) TREAT_AS(type, name)
#define TREAT_ALL_AS_HELPER_2(type, name, ...) TREAT_AS(type, name), TREAT_ALL_AS_HELPER_1(type, __VA_ARGS__)
#define TREAT_ALL_AS_HELPER_3(type, name, ...) TREAT_AS(type, name), TREAT_ALL_AS_HELPER_2(type, __VA_ARGS__)
#define TREAT_ALL_AS_HELPER_4(type, name, ...) TREAT_AS(type, name), TREAT_ALL_AS_HELPER_3(type, __VA_ARGS__)
#define TREAT_ALL_AS_HELPER_5(type, name, ...) TREAT_AS(type, name), TREAT_ALL_AS_HELPER_4(type, __VA_ARGS__)
// expand as you will
#define TREAT_ALL_AS(type, count, ...) SPLICE(TREAT_ALL_AS_HELPER_, count)(type, __VA_ARGS__)
现在用作
double x = [TREAT_ALL_AS(double, 4, a, b, c, d)] {
return a/b/c/d+c/d+a; }();
你也可以automatically count the number of variadic macro arguments.
但老实说,IMO 最好只编写一个命名函数。