【问题标题】:Fastest way to modify one digit of an integer修改一位整数的最快方法
【发布时间】:2010-10-04 18:23:17
【问题描述】:

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

例子

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

编辑:最快,我绝对是指更快的性能。没有字符串处理。

【问题讨论】:

  • 那么,您的索引从左到右计数(从最重要到最不重要?)
  • 我认为我们可以假设基数为 10?
  • 嗯,转换为字符串,交换数字,然后转换回整数是我所知道的最快的 code 方法,但有些事情告诉我这不是你的'正在寻找...
  • @Adam:哪些测试让您确定在这种情况下字符串处理的性能不能令人满意?我问是因为,很可能,下一个遇到您提出的任何解决方案的开发人员可能会对您非常不满。这对个人教育来说很好,但不要在没有充分理由的情况下将其放入软件中。
  • 这是不是语言无关的。解决方案将取决于它是否被解释(以及如何解释)、它是否在 VM 上运行(哪个)以及它是否被编译(哪个架构)。这可能在某种程度上取决于所有这些。

标签: algorithm language-agnostic number-theory


【解决方案1】:

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

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

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

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

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;
    }
}

【讨论】:

    【解决方案2】:

    如果您的索引从最低有效位开始,您可以执行类似的操作

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

    但是由于您的索引是向后的,因此字符串可能是要走的路。它也将更具可读性和可维护性。

    【讨论】:

    • 呃...最后的表达不正确。应该是x / (p*10) * (p*10) + ... 等等。
    【解决方案3】:
    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

    附: ruslik 的回答做得更优雅:)

    【讨论】:

      【解决方案4】:

      您首先需要弄清楚您的输入中有多少位数字。我可以想到两种方法,一种是循环,另一种是对数。这是循环版本。对于负数和零输入以及索引超出范围(可能还有其他条件),这将失败,但这是一个起点。

      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)
      

      附:这是工作的 Python 代码。像这样简单的事情的原理很容易解决,但细节非常棘手,你真的需要迭代一下。在这种情况下,我从要减去旧数字并添加新数字的原则开始;从那里得到正确的乘数是一个问题。

      【讨论】:

        【解决方案5】:

        如果您谈论性能,则必须具体说明您的计算平台。

        我会通过将数字转换成十进制数字对来解决这个问题,每对 4 位。

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

        然后我会将数字重新组合在一起。

        有些汇编程序做得很好。

        【讨论】:

        • 这应该是评论,而不是答案。
        • 这是评论,不是答案
        • 平心而论,无论我使用 Fortran 90 想出什么,都会有一个聪明的人使用 PowerPC 汇编程序更快地完成它。
        猜你喜欢
        • 1970-01-01
        • 2019-08-16
        • 2012-09-08
        • 2014-03-12
        • 2020-12-26
        • 2011-07-08
        • 1970-01-01
        • 1970-01-01
        • 2012-06-07
        相关资源
        最近更新 更多