C++20新特性—数学计算库

C++20引入了新的数学计算库,包括<numbers>头文件中的数学常数,增强了位操作功能,如按位计数,提供了std::endian用于endianness判断。此外,还添加了std::midpoint、std::lerp等实用函数,以及std::accumulate、std::partial_sum等数值计算工具,进一步丰富了C++的数学和算法支持。

数学常数

增加了<numbers>,其中定义了常用的数学常数,如e,log2e,sqrt2,sqrt3等。

Bit操作

新增了一些列bit的操作,如按位判断有几个0,几个1等,具体内容参加库函数说明,用法示意如下(std::bit_cast在gcc10.2中未被支持):

void test_bit() 
{
    std::uint8_t num= 0b00110010;
    std::cout << std::boolalpha;
    std::cout << "std::has_single_bit(0b00110010): " << std::has_single_bit(num) << '\n';
    std::cout << "std::bit_ceil(0b00110010): " << std::bitset<8>(std::bit_ceil(num)) << '\n';
    std::cout << "std::bit_floor(0b00110010): " << std::bitset<8>(std::bit_floor(num)) << '\n';
    std::cout << "std::bit_width(5u): " << std::bit_width(5u) << '\n';
    std::cout << "std::rotl(0b00110010, 2): " << std::bitset<8>(std::rotl(num, 2)) << '\n';
    std::cout << "std::rotr(0b00110010, 2): " << std::bitset<8>(std::rotr(num, 2)) << '\n';
    std::cout << "std::countl_zero(0b00110010): " << std::countl_zero(num) << '\n';
    std::cout << "std::countl_one(0b00110010): " << std::countl_one(num) << '\n';
    std::cout << "std::countr_zero(0b00110010): " << std::countr_zero(num) << '\n';
    std::cout << "std::countr_one(0b00110010): " << std::countr_one(num) << '\n';
    std::cout << "std::popcount(0b00110010): " << std::popcount(num) << '\n';
}

endian判断

std::endian 在<bit>中定义,仅是一个简单的判断,用法示意如下:

void test_endian() {
     if constexpr (std::endian::native == std::endian::big) {
        std::cout << "big-endian" << '\n';
    }
    else if constexpr (std::endian::native == std::endian::little) {
        std::cout << "little-endian"  << '\n';
    }
    else {
        std::cout << "mixed-endian"  << '\n';
    }
}

std::midpoint

定义在<numeric>中,std::midpoint(a,b)的意思就是a+(b-a)/2;

std::lerp

定义在<cmath>中,std::lerp(a,b,t)的意思就是a+(b-a)*t;

std::accumulate

定义在<numeric>中,缺省形式std:: accumulate (a.begin(), a.end(), 0)表示集合a元素的累加,

比较复杂的形式std:: accumulate (a.begin(), a.end(),init, op)表示a中的元素运用op进行积累运算,即:  Init[i]=op1(init[i-1],a[i])),其中i从1到n, init[0]=init, a[0]=a.begin(), a[n-1]=a.end(),最终init[n-1]就是返回值(标量)。

std::partial_sum

定义在<numeric>中,与std::accumulate类似,但将每次计算的中间结果保存到集合中,因此它的输出是一个集合而不是最终的一个标量值。

std::inner_product

定义在<numeric>中,缺省形式std::inner_product(a.begin(), a.end(), b.begin(), 0)表示集合a和b的内积,比较复杂的形式std::inner_product(a.begin(), a.end(), b.begin(), init, op1, op2)表示a中的元素与b中的元素经过op2运算后再运用op1进行积累运算,即:  Init[i]=op1(init[i-1],op2(a[i],b[i])),其中i从1到n, init[0]=init, a[0]=a.begin(), b[0]=b.begin(),a[n-1]=a.end(),最终init[n-1]就是返回值,大概最终结果是一个标量,所以也把它叫“内积”吧。

std::adjacent_difference

定义在<numeric>中,表示将op(当前元素,后一个元素)的结果保存到集合中,op为空时就是相减,因此叫adjacent_difference,输出是一个集合。

std::transform

定义在<algorithm>中,表示集合元素的变换,即将一个集合中的元素经过一元运算或两个集合中元素经过二元运算后,结果再保存到集合中,上面涉及的集合可以是一个集合,两个集合或三个集合。

void test_numeric()
{
    int r1=std::midpoint(5,8);           //6
    float 2=std::lerp(5,8,2.0);           //11
    std::vector<int> a{0, 1, 2, 3, 4};
int r3= std::accumulate(a.begin(), a.end(), 0);      //10
auto dash_fold = [](std::string a, int b) { return std::move(a) + '-' + std::to_string(b); };
std::string r4 = std::accumulate(std::next(v.rbegin()), v.rend(),
                                     std::to_string(v.back()), // start with last element
                                    dash_fold);        //4-3-2-1-0
    std::vector<int> v(a.size());
    auto op=[](const int a, const int b)->int{ return a+b*2;};
    std::partial_sum(a.begin(), a.end(), v.begin(),  op);   //{0,2,6,12,20}
    std::adjacent_difference(a.begin(), a.end(), v.begin());  //{0,1,1,1,1}

std::vector<int> b{5, 4, 2, 3, 4};
    int r5 = std::inner_product(a.begin(), a.end(), b.begin(), 0);        //33
    int r6 = std::inner_product(a.begin(), a.end(), b.begin(),0, std::plus<>(), std::equal_to<>());         //3
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值