分而治之-C/C++库函数和运算符是最理想的函数和运算符吗

divide and conquer - Are C/C++ library functions and operators the most optimal ones?

本文关键字:运算符 最理想 函数 C++ 库函数 分而治之      更新时间:2023-10-16

因此,在除法&我们被教导的征服课程:

  1. Karatsuba乘法
  2. 快速求幂

现在,给定2个正整数a和b,operator::*karatsuba(a,b)快,或者pow(a,b)比快

int fast_expo(int Base, int exp)
{
    if (exp == 0) {
        return 1;
    }
    if (exp == 1) {
        return Base
    }
    if (exp % 2 == 0) {
        return fast_expo(Base, exp / 2) * fast_expo(Base, exp / 2);
    }
    else {
        return base * fast_expo(Base, exp / 2) * fast_expo(Base, exp / 2);
    }
}

我问这个问题是因为我想知道它们是否只是一个教学目的,或者它们已经在C/C++语言中基本实现了

Karatsuba乘法是一种用于大整数的特殊技术。它不能与内置的C++*运算符相比,后者将基本类型的操作数(如intdouble(相乘在一起。

要利用Karatsuba,您必须使用至少由8个单词组成的多精度整数。(如果这些是64位字,则为512位(。根据这个问题的公认答案,Karatsuba变得有利的盈亏平衡点在8到24个机器词之间。

与一对类型为double的浮点操作数一起使用的pow函数与您的fast_expo(与类型为int的操作数一起工作(不可同日而语。它们是不同的功能,有不同的要求。使用pow,可以计算5:pow(5, 1/3.0)的立方根。如果这是你想要计算的,那么fast_expo无论有多快都没有用。

不能保证编译器或C库的pow绝对是机器对两个双精度浮点数求幂的最快方法。

浮点中的优化声明可能很棘手,因为通常情况下,"同一"函数的多个实现直到最后一位都不会给出完全相同的结果。您可能可以编写一个精度仅为小数点后五位的快速my_pow,在您的应用程序中,这种近似可能绰绰有余。你打败图书馆了吗?几乎不您的fast函数不符合将其作为库中pow的替代品的要求。

operator::*和其他标准运算符通常映射到硬件提供的基元。如果不存在这样的基元(例如,IA32上的64位long long(,编译器会以性能为代价来模拟它们(gcc在libgcc中这样做(。

std::pow相同。它是标准库的一部分,并没有强制要求以某种方式实现。GNU libc将pow(a,b)实现为exp(log(a) * b)。CCD_ 23和CCD_。


至于你的建议:

小数字的Karatsuba乘法不值得。处理器提供的乘法机指令已经针对使用中的标准数据类型的速度和功耗进行了优化。有了更大的数字,10-20倍的寄存器容量,它开始有回报:

在GNU MP Bignum库中,曾经有一个默认的非模块乘法的KARATSUBA_THRESHOLD高达32(也就是说,当n>=32w与典型的w=32时使用Karatsuba(;模幂运算的最优阈值趋向于显著更高。在现代CPU上,软件中的Karatsuba倾向于对于P-256上的ECDSA(n=256w=32w=64(,但是可以想象对于RSA中使用的宽得多的模量是有用的。

下面列出了GNUMP使用的乘法算法及其各自的阈值。

快速求幂不适用于非整数幂,因此它实际上无法与pow相比。

检查操作速度的一个好方法是测量它。如果你运行大约十亿次计算,看看执行需要多少时间,你就有答案了。

有一点需要注意。我相信%是相当昂贵的。有一种更快的方法可以检查某个东西是否可以被2:整除

check_div_two(int number)
{
    return ((number>>1) & 0x01);
}

通过这种方式,你只是做了一点改变,并与口罩进行了比较。我认为这是一个比较便宜的操作。

内置类型的*运算符几乎肯定会作为单个CPU乘法指令来实现。所以归根结底,这是一个硬件问题,而不是语言问题。在没有直接硬件支持的情况下,可能会生成更长的代码序列,可能是函数调用

可以肯定的是,芯片制造商(英特尔、AMD等(花费了大量精力使算术运算尽可能高效。

相关文章: