假设我有一个int x = 54897
旧数字索引(基于0),以及该数字的新值。获得新价值的最快方法是什么?
实施例
x = 54897
index = 3
value = 2
y = f(x, index, value) // => 54827
编辑:通过最快,我绝对意味着更快的性能。没有字符串处理。
答案 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)
计算“掩码”M
:10提升到index
的幂,其中index
是从右边开始的从零开始的索引。如果您需要从左侧开始索引,请相应地重新计算index
。
计算“前缀”PRE = x / (M * 10) * (M * 10)
计算“后缀”SUF = x % M
计算新的“中间部分”MID = value * M
生成新号码new_x = PRE + MID + POST
。
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位来实现此目的。
然后我会找到并处理需要修改的对作为字节。
然后我会将这个号码重新组合在一起。
有些装配工可以做得很好。