[英]Is it necessary to cast literal constants in templated functions?
我正在編寫必須以單精度和雙精度編譯的代碼。 原始版本僅具有雙精度,但是我現在嘗試通過使用模板啟用單精度。
我的問題是:是否需要使用static_cast<TF>(1.)
將1.
和7.8
static_cast<TF>(1.)
轉換為指定的類型,否則編譯器會處理嗎? 我發現演員表並不十分漂亮,並且寧願遠離它。 (我還有其他更長的函數,並且包含更多的文字常量)。
template<typename TF>
inline TF phih_stable(const TF zeta)
{
// Hogstrom, 1988
return 1. + 7.8*zeta;
}
強制轉換和隱式轉換是兩件事。 對於此示例,您可以將模板函數視為兩個重載函數,但其中包含相同的代碼。 在接口級別(參數,返回值),編譯器將生成隱式轉換。
現在,您將不得不問自己的問題是:那些隱式轉換是否可以實現我想要的? 如果他們這樣做,則保持原樣。 如果不這樣做,則可以嘗試添加顯式轉換(也許使用像TF(1.)
這樣的函數樣式轉換),或者,您可以將此函數專門用於double
和float
。
另一個不太通用但也許在這里可行的選擇是,切換代碼,即為單精度float
編寫代碼,然后讓編譯器應用其隱式轉換。 由於轉換通常只流向較大的類型,它應該符合兩個double
和float
不會產生任何開銷float
。
當您這樣做時:
return 1. + 7.8*zeta;
文字1.
和7.8
是double
,因此,如果zeta
是float
,則將其首先轉換為double
,然后整個計算將以double精度完成,結果將轉換為float
,這等效至:
return (float)(1. + 7.8 * (double)zeta);
否則,這等效於調用phih_stable(double)
並將結果存儲在float
,因此您的模板對於float
沒有用。
如果要以單精度進行計算,則需要強制轉換1 :
return TF(1.) + TF(7.8) * zeta;
使用1.f
和7.8f
怎么7.8f
? 問題是由於浮點精度, (double)7.8f != 7.8
。 差異約為1e-7
7.8f
的實際存儲值(假設32位float
)為:
7.80000019073486328125
7.8
的實際存儲值(假設64位double
)為:
7.79999999999999982236431605997
因此,您必須問自己是否接受這種精度損失。
您可以比較以下兩個實現:
template <class T>
constexpr T phih_stable_cast(T t) {
return T(1l) + T(7.8l) * t;
}
template <class T>
constexpr T phih_stable_float(T t) {
return 1.f + 7.8f * t;
}
以及以下斷言:
static_assert(phih_stable_cast(3.4f) == 1. + 7.8f * 3.4f, "");
static_assert(phih_stable_cast(3.4) == 1. + 7.8 * 3.4, "");
static_assert(phih_stable_cast(3.4l) == 1. + 7.8l * 3.4l, "");
static_assert(phih_stable_float(3.4f) == 1.f + 7.8f * 3.4f, "");
static_assert(phih_stable_float(3.4) == 1. + 7.8 * 3.4, "");
static_assert(phih_stable_float(3.4l) == 1.l + 7.8l * 3.4l, "");
最后兩個斷言由於執行計算時的精度損失而失敗。
1當您將函數與long double
一起使用時,您甚至應該從long double
轉換,以免失去精度: return TF(1.l) + TF(7.8l) * zeta;
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.