修改整数的一位数的最快方法

时间:2010-10-04 18:23:17

标签: algorithm language-agnostic number-theory

假设我有一个int x = 54897旧数字索引(基于0),以及该数字的新值。获得新价值的最快方法是什么?

实施例

x = 54897
index = 3
value = 2
y = f(x, index, value) // => 54827

编辑:通过最快,我绝对意味着更快的性能。没有字符串处理。

5 个答案:

答案 0 :(得分:3)

在最简单的情况下(考虑到数字从LSB编号到MSB,第一个数字为0)并且知道旧数字,我们可以这么简单:

num += (new_digit - old_digit) * 10**pos;

对于我们需要的真正问题:

1)pos的MSB优先版本,可能会花费您log()或最多log10(MAX_INT)个除以10(可以使用二进制搜索进行改进)。

2)来自pos的数字,最多需要2个分区(或零,使用步骤1的结果)。

您还可以使用x86中的特殊fpu指令,该指令能够在BCD中保存浮点数(我不知道它有多慢)。

更新:第一步可以更快地完成,没有任何划分,使用这样的二进制搜索:

int my_log10(unsigned short n){
    // short: 0.. 64k -> 1.. 5 digits 
    if (n < 1000){  // 1..3
        if (n <  10) return 1;
        if (n < 100) return 2;
        return 3;
    } else { // 4..5
        if (n < 10000) return 4;
        return 5;
    }
}

答案 1 :(得分:2)

如果您的索引以最低有效数字开头,您可以执行类似

的操作
p = pow(10,index);
x = (x / (p*10) * (p*10) + value * p + x % p).

但是由于你的索引是向后的,所以可能是一个字符串。它也更具可读性和可维护性。

答案 2 :(得分:1)

  1. 计算“掩码”M:10提升到index的幂,其中index是从右边开始的从零开始的索引。如果您需要从左侧开始索引,请相应地重新计算index

  2. 计算“前缀”PRE = x / (M * 10) * (M * 10)

  3. 计算“后缀”SUF = x % M

  4. 计算新的“中间部分”MID = value * M

  5. 生成新号码new_x = PRE + MID + POST

  6. P.S。 ruslik的答案更优雅:)

答案 3 :(得分:1)

您需要先确定输入中有多少位数。我可以想到两种方法,一种是循环,一种是对数。这是循环版本。这对于负输入和零输入都会失败,当索引超出范围时,可能还有其他条件,但这是一个起点。

def f(x, index, value):
    place = 1
    residual = x
    while residual > 0:
        if index < 0:
            place *= 10
        index -= 1
        residual /= 10
    digit = (x / place) % 10
    return x - (place * digit) + (place * value)

P.S。这是有效的Python代码。像这样简单的原理很容易解决,但细节是如此棘手,你真的需要迭代它。在这种情况下,我开始的原则是我想减去旧数字并添加新数字;从那里获得正确的乘数是个问题。

答案 4 :(得分:0)

如果你在谈论性能,你必须具体了解你的计算平台。

我会通过将数字转换成十进制数字对,每个4位来实现此目的。

然后我会找到并处理需要修改的对作为字节。

然后我会将这个号码重新组合在一起。

有些装配工可以做得很好。