【问题标题】:Recursive Karatsuba Algorithm giving Imprecise Answers给出不精确答案的递归 Karatsuba 算法
【发布时间】:2020-09-12 13:59:57
【问题描述】:

我一直在尝试在 C++ 中为两个相同长度的大数实现 Karatsuba 乘法算法。我的代码对于较小的数字(例如 3456*1492)表现正常,但对于较大的数字(例如 64 位数字)则失败。它通常会得到正确的前几位数字,但之后会出错。我正在使用 Boost 多精度库来处理大整数。

我的代码如下:

cpp_int karatsuba(cpp_int n1, cpp_int n2) {
    if (n1 < 10 || n2 < 10) {
        return n1 * n2;
    }

    int len = countDigits(n1);

    cpp_int a = n1 / cpp_int(pow(10, len/2));
    cpp_int b = n1 % cpp_int(pow(10, len/2));
    cpp_int c = n2 / cpp_int(pow(10, len/2));
    cpp_int d = n2 % cpp_int(pow(10, len/2));

    cpp_int sub1 = karatsuba(a, c);
    cpp_int sub2 = karatsuba(b, d);
    cpp_int sub3 = karatsuba(a+b, c+d) - sub1 - sub2;

    return sub1 * cpp_int(pow(10, len)) + sub3 * cpp_int(pow(10, len/2)) + sub2;
}

我已将我的代码与几个在线实现进行了比较,但我无法找到任何会影响答案的显着差异。 cpp_int 类型的精度可能存在问题,还是我的代码存在问题?

非常感谢您的帮助!

【问题讨论】:

  • countDigits的实现是什么?
  • 它失败的数字太大而无法放入double,但我遇到了与uint1024_t相同的问题。
  • countDigits 反复除以 10 直到数字等于 0 并计算除数。我已经测试了countDigits,所以我相信问题不存在。
  • 您看过 Boost.Multiprecision 中的 Karatsuba 了吗? github.com/boostorg/multiprecision/blob/develop/include/boost/…
  • 为什么要在乘法中使用pow?这很疯狂,并且否定了 Karatsuba 复杂性的好处,因为 pow 是更高的操作(如果你的 Karatsuba 被使用 btw,它还使用乘法,如果你的 Karatsuba 被使用,则会堆栈溢出。)并且慢得多......使用 2 基数的幂进行拆分和位操作(位班次,和掩蔽......)代替。另见Fast bignum square computation

标签: c++ algorithm math boost karatsuba


【解决方案1】:

我怀疑一个问题是 pow 返回的浮点表示被不准确地转换为 cpp_int。

使用 pow 的多精度版本可能会有所帮助。

此外,len/2 向下取整,因此在计算 pow(10,len) 时,应该改为 pow(10,(len/2)*2)。

【讨论】:

  • 切换到 pow 的多精度实现解决了我在精度方面遇到的问题。非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-10
  • 2013-04-12
  • 2021-11-24
  • 1970-01-01
相关资源
最近更新 更多