У меня есть несколько блоков кода, которые делают:
float total = <some float>;
double some_dbl = <some double>;
total *= some_dbl;
Это вызывает предупреждение компилятора, которое я хочу заткнуть, но мне не нравится отключать такие предупреждения - вместо этого я предпочитаю явно использовать типы по мере необходимости. Что заставило меня думать... это (float)(total * some_dbl)
более точно, чем total * (float)some_dbl
? Является ли это компилятором или платформой?
Пример лучшего кода (связанный ниже):
#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:
Итак, я выстрелил. С примерами, которые я попробовал, я быстро нашел, где total * (float)(some_dbl)
представляется более точным. Я предполагаю, что это не всегда так, но это скорее удача ничьей, или компилятор усекает двойники, чтобы плавать, а не округлять, что приводит к потенциально худшим результатам. См.: http://ideone.com/sRXj1z
Изменить 2: Я подтвердил с помощью std::nextafter
, что (float)(total * some_dbl)
возвращает усеченное значение и обновляет связанный код. Удивительно: если компилятор в этом случае всегда усекает удваивает, то вы можете сказать (float)some_dbl <= some_dbl
, что затем означает with_cast <= no_cast
. Однако, это не так! with_cast
не только больше, чем no_cast
, но и ближе к фактическому значению, что является неожиданным, учитывая, что мы отбрасываем информацию до того, как произойдет умножение.