如何优化将无符号任意精度整数转换为字符串以进行打印?

问题描述

我正在用 C++ 编写一个无符号的任意精度整数类,作为我自己的练习。在运行一些基准测试(计算某个数字的斐波那契数列)时,我注意到将我的类转换为用于打印的字符串大约占用了总运行时间的 40%。目前,我正在使用传统的小学方法将整数除以 10 以获得可打印的字符串,并且想知道是否有更快的方法

我曾尝试实施 Newton-Raphson 划分,但即使使用 Karatsuba 实施,它仍然比传统方法慢得多。

我目前的想法是以足够的精度生成数字 0.1,以便我可以用乘法运算代替除法运算。当然,这种方法在尝试打印大数时会导致舍入错误。我的一个测试中的一个例子:

Print test:   11111111112345678906735299999996
My old print: 11111111112345678906735300000000

这是我的问题:

  1. 有没有办法知道计算 0.1 需要多少精度,这样当我将它乘以我要打印的数字时,它不会有明显的舍入误差?即,当转换回整数时,舍入误差将被移走。
  2. 在处理任意精度时,是否有其他方法可以优化除以常数?在我看来,我可能会找到某种方法,对最高有效位使用这种乘法方法,对最低有效位使用小学方法,但我怀疑运行时的回报是否重要。

注意:我将整数存储为 std::vector<bool> 并使用 -O3 优化标志。这方面的任何信息都会有很大帮助!提前致谢。

编辑: 在创建这个类时,我最初的想法是保持它相当基本。即因为内存中的整数只是一个位数组,那么我将如何存储我的位。存储是不言自明的,如果 arr 是我的向量,那么 arr[0] 代表 2^0,而 arr[1] 是 2^1,依此类推。

对于任何想知道的人来说,我最初对 to_string 的丑陋实现:

std::string uInt::to_string() const {
    if (*this == ZERO) return std::string("0");
    uInt n(*this),mod;
    std::string result("");
    while (n != ZERO) {
        std::pair<uInt,uInt> div_mod_result = n.div_and_mod(TEN);
        mod = div_mod_result.second;
        n = div_mod_result.first;
        if (mod == ZERO)
            result = '0' + result;
        else if (mod == ONE)
            result = '1' + result;
        else if (mod == TWO)
            result = '2' + result;
        else if (mod == THREE)
            result = '3' + result;
        else if (mod == FOUR)
            result = '4' + result;
        else if (mod == FIVE)
            result = '5' + result;
        else if (mod == SIX)
            result = '6' + result;
        else if (mod == SEVEN)
            result = '7' + result;
        else if (mod == EIGHT)
            result = '8' + result;
        else if (mod == NINE)
            result = '9' + result;
        else {
            throw std::runtime_error("ERROR: To String Failed");
        }
    }
    return result;
}

我的定点尝试:

std::string uInt::to_string() const {
    if (this->bits.empty()) return std::string("0");
    uint64_t precision = this->bits.size(); // Unsure what precision would be necessary
    one_over_ten = uInt::get_one_over_ten(precision);
    mask = (ONE << precision) - ONE;
    uInt n(*this),mod;
    std::string result("");
    while (n.bits.size()) {
        floating_point_result = n * one_over_ten; // Leaves me with n/10 with precision fraction bits
        mod = ((floating_point_result & mask) * TEN) >> precision; // Extracts the fraction
                                                                   // bits,multiplies by ten,// then converts to an integer
        n = floating_point_result >> precision; // Turns n back into an integer
        /* Same if chain as before */
    }
    return result;
}

希望这能更好地解释我一直在尝试的东西。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)