簡體   English   中英

是否有必要在模板函數中強制轉換文字常量?

[英]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.)這樣的函數樣式轉換),或者,您可以將此函數專門用於doublefloat

另一個不太通用但也許在這里可行的選擇是,切換代碼,即為單精度float編寫代碼,然后讓編譯器應用其隱式轉換。 由於轉換通常只流向較大的類型,它應該符合兩個doublefloat不會產生任何開銷float

當您這樣做時:

return 1. + 7.8*zeta;

文字1.7.8double ,因此,如果zetafloat ,則將其首先轉換為double ,然后整個計算將以double精度完成,結果將轉換為float ,這等效至:

return (float)(1. + 7.8 * (double)zeta);

否則,這等效於調用phih_stable(double)並將結果存儲在float ,因此您的模板對於float沒有用。

如果要以單精度進行計算,則需要強制轉換1

return TF(1.) + TF(7.8) * zeta;

使用1.f7.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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM