這篇是延續之前的《C++11 的一些數值函式庫》,繼續來整理 C++17、C++20 在數值函式庫上的變化。
首先,在 <numeric> 這個 header 裡面(參考),又加入了很多 template 函式可以使用,其中也包含了 gcd(對大公因數)、lcm(最小公倍數)、inner_product(內積)等等;雖然不能說沒用,但是老實說,有需要的人大概都已經有自己的方案了吧…
另外,這次也還有支援平行化的 reduce(),以及在平行化演算法裡面很常見的 inclusive_scan()、exclusive_scan() 可以使用。
另外,C++20 也多了一個計算中點(平均值)的 midpoint();雖然基本上是個 ( a + b ) / 2 的計算,不過 std::midpoint() 的實作相對複雜、也避免了可能發生的 overflow 的問題。
下面是一個例子:
#include <cstdint> #include <limits> #include <numeric> #include <iostream> int main() {
std::uint32_t a = std::numeric_limits<std::uint32_t>::max();
std::uint32_t b = std::numeric_limits<std::uint32_t>::max() - 2;
std::cout
<< "a: " << a << 'n'
<< "b: " << b << 'n'
<< "Incorrect (overflow and wrapping): " << (a + b) / 2 << 'n'
<< "Correct: " << std::midpoint(a, b) << "nn"; }
這邊直接使用 ( a + b ) / 2 來計算的話,會因為 a + b 超過了 uint32_t 的範圍,所以結果會出現錯誤;而使用 std::midpoint() 則不會有這個問題。
而除了中點外,C++20 也在 <cmath> 中提供了一組線性內插的函式、std::lerp();他的計算基本上就是 a + t * ( b – a ) 這樣的形式。不過由於 lerp() 不是 template 的形式,所以能支援的型別就相對有限了;這點個人覺得還滿可惜的…
C++17 也在 <cmath> 中提供了一些數學的特殊函式(mathematical special functions、參考),包含了 beta、gamma、以及一些微積分函式、多項式。
不過 Heresy 必須老實說,個人對這些東西都不熟就是了。
最後,C++20 也終於透過 <numbers> 定義了包括 pi、e、ln2 這類常見的數學常數;使用方法基本上如下:
#include <numbers> #include <iostream> int main() { std::cout << std::numbers::pi << "n"; }
這邊的 std::numbers::pi 是透過 constexpr 定義的 double 型別,如果需要其他型別的話,也可以透過 std::numbers::pi_v<> 的形式來取得,例如:
float fPi = std::numbers::pi_v<float>;
(額外參考《Math constants》)
這篇大概就是這樣了。主要其實只是要記錄一下有哪些新的東西可以用,以後有需要可以回來撈而已。 XD
而很多東西太專業了,現在也就先跳過了。