I have some blocks of code that do:
float total = <some float>;
double some_dbl = <some double>;
total *= some_dbl;
This elicits a compiler warning which I want to shut up, but I don't like turning off such warnings - instead, I would rather explicitly cast types as needed. Which got me thinking...is a (float)(total * some_dbl)
more accurate than total * (float)some_dbl
? Is it compiler or platform specific?
Better code example (linked below):
#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;
int main() {
double d_total = 1.2345678;
float f_total = (float)d_total;
double some_dbl = 6.7809123;
double actual = (d_total * some_dbl);
float no_cast = (float)(f_total * some_dbl);
float with_cast = (float)(f_total * (float)some_dbl);
cout << "actual: " << setprecision(25) << actual << endl;
cout << "no_cast: " << setprecision(25) << no_cast << endl;
cout << "with_cast: " << setprecision(25) << with_cast << endl;
cout << "no_cast, nextafter: " << setprecision(25) << nextafter(no_cast, 500.0f) << endl;
cout << endl;
cout << "Diff no_cast: " << setprecision(25) << actual - no_cast << endl;
cout << "Diff with_cast: " << setprecision(25) << with_cast - actual << endl;
return 0;
}
Edit:
So, I gave this a shot. With the examples I tried, I did find one quickly where total * (float)(some_dbl)
appears to be more accurate. I assume this isn't going to always be the case, but is instead luck of the draw, or the compiler is truncating doubles to get to float, rather than rounding, causing potentially worse results. See: http://ideone.com/sRXj1z
Edit 2: I confirmed using std::nextafter
that (float)(total * some_dbl)
is returning the truncated value, and updated the linked code. It is quite surprising: if the compiler in this case is always truncating doubles, than you can say (float)some_dbl <= some_dbl
, which then implies with_cast <= no_cast
. However, this is not the case! with_cast
is not only greater than no_cast
, but it is closer to the actual value as well, which is kinda surprising, given that we are discarding information before the multiplication occurs.