int a{5},b{2},c{9};
double d = (double)a / (double)b + (double)c;
Or I can use static_cast
. Either way is verbose, especially when the formula is long. Is there a better solution?
int a{5},b{2},c{9};
double d = (double)a / (double)b + (double)c;
Or I can use static_cast
. Either way is verbose, especially when the formula is long. Is there a better solution?
You can multiply by 1.0:
int a{5}, b{2}, c{9};
double d = 1.0 * a / b + 1.0 * c;
And when you work with sums you can add to 0.0:
double d = 0.0 + a - b + c;
Most compilers perform optimization such that the meaningless operation is not evaluated. Only type conversion is done.
Remember that you only need to cast the first member in each division/multiply group. Do so in any manner that seems reasonable. And simple addition/substraction (with no other type multipliers/divisors) is casted too. Compilers guarantee casting. So your example:
double d = (double)a / (double)b + (double)c;
Really may be rewritten like this:
double d = (double)a / b + c;
double d = 1.0 * a / b + c;
double d = static_cast<double>(a) / b + c;
Some more examples:
double d = (double)a / b + (double)c / d + e;
double d = 1.0 * a / b + 1.0 * c / d + e;
double d = static_cast<double>(a) / b + static_cast<double>(c) / d + e;
Is there a better solution?
Yes. Express intent through functions.
Marvel as the optimiser emits perfectly efficient assembler. Enjoy the accolades of your colleagues who gaze in wonder at your awesomely readable and maintainable code:
#include <iostream>
auto a_over_b_plus_c(double a, double b, double c)
{
double d = a / b + c;
return d;
}
int main()
{
int a = 5, b = 2, c = 9;
std::cout << a_over_b_plus_c(a, b, c) << std::endl;
}
For fun, here's a solution based on tuples & lambdas:
#include <iostream>
#include <tuple>
template<class T, class...Args>
auto to(Args&&...args)
{
return std::make_tuple(T(std::forward<Args>(args))...);
}
int main()
{
int a = 5, b = 2, c = 9;
auto calc = [](auto&& vals) {
auto& a = std::get<0>(vals);
auto& b = std::get<1>(vals);
auto& c = std::get<2>(vals);
return a / b + c;
};
auto result = calc(to<double>(a, b, c));
std::cout << result << std::endl;
}
... and something perhaps more readable...
#include <iostream>
#include <tuple>
#include <complex>
template<class T, class F, class...Args>
auto with(F f, Args&&...args)
{
return f(T(std::forward<Args>(args))...);
}
int main()
{
int a = 5, b = 2, c = 9;
auto calc = [](auto&& a, auto&& b, auto&& c) {
return a / b + c;
};
auto result = with<double>(calc, a, b, c);
auto result2 = with<float>(calc, a, b, c);
auto result3 = with<std::complex<double>>(calc, a, b, c);
auto result4 = with<std::complex<float>>(calc, a, b, c);
std::cout << result << std::endl;
std::cout << result2 << std::endl;
std::cout << result3 << std::endl;
}
This works but all you need is a single 1.0*
in front of a
int a{5},b{2},c{9};
double d = (double)a / (double)b + (double)c;
int a{5},b{2},c{9};
double d = 1.0*a / b + c;
The rules of precedence and implicit conversion will cause all the variables to be converted to doubles.
One thing to be careful of is grouped variables which will need to have their own 1.0*
or 0.0+
as appropriate:
int a{5},b{2},c{9};
double d = a / (0.0 + b + c);
int a{5},b{2},c{9};
double d = a / (1.0 * b * c);
Alternately, one use use a static cast on the associated variable. I prefer the smaller version as the 1.0*
or 0.0+
both scream out implicit conversion to doubles.
int a{5},b{2},c{9};
double d = a / (static_cast<double>(b) * c);