【问题标题】:Convert string to number & vice versa complexity将字符串转换为数字,反之亦然
【发布时间】:2011-05-27 20:37:52
【问题描述】:

将字符串转换为等效数字或反之亦然的复杂性是多少?它会根据编程语言而改变吗?

从表面上看,需要遍历整个字符串才能将其转换为数字,所以是O(n),还是使用了某种类型转换?

当我编写一个例程来检查给定的数字是否是回文时,这个疑问就出现了。一种方法是继续将数字除以基数(此处为 10),累积数字,然后将它们放在最后。示例:309/10=rem(9)、30/10=rem(0)、3/10=rem(3)。我们得到 903。

我采用的另一种方法是将这个数字转换为字符串,由于字符串有很多成员函数可以拆分、反转等,所以代码更短更简洁,但这是最好的方法吗?

【问题讨论】:

  • 在您的情况下,您认为“N”是什么?
  • @TToni N 的大小没有上限...
  • 好吧,我换个方式问:假设您将 N 视为输入字符串的长度并询问将该字符串解析为数字的算法复杂性,我是否正确?

标签: algorithm string complexity-theory math string-conversion


【解决方案1】:

C# 和 C/C++ 在表示(可能的)数值的字符串中没有任何特殊信息。因此,他们需要在转换时逐位解析字符串。

但是,位数是有限的,所以我们只有 O(1):转换时间是有界的(通常是最大数字的转换)。对于 32 位 int,转换必须考虑最多 10 个十进制数字(可能还有一个符号)。

从字符串转换实际上也是 O(1),因为在解析它的过程中,只考虑有限数量的字符(在 32 位 int 的情况下为 10+1)就足够了。

严格来说,我们不能将O-notation 用于int 到字符串的转换,因为int 的最大值是有界的。无论如何,转换所需的时间(双向)受到一个常数的限制。

正如@Charles 建议的那样,其他语言(Python)实际上可以使用任意精度的数字。对于解析这样的数字,时间是O(number of digits),这两个转换分别是O(string length)O(log(number))。对于任意精度的数字,不能更快地做到这一点,因为对于这两种转换都必须考虑每个数字。对于有限精度数的转换,同样的O(1) 推理适用。但是我自己并没有在 Python 中分析解析,所以那里可能使用了效率较低的算法。


编辑:按照@Steve 的建议,我检查了 C/C++ 和 C# 中的解析是否跳过了初始空格,因此 string->int 转换的时间实际上是O(input length)。如果已知字符串被修剪,则再次转换为O(1)

【讨论】:

  • 当然我们可以使用大 O 表示法,不使用大整数时我们只得到 O(1)。
  • @larsmans:我明确谈论的是没有内置 bigint 的 C/C++ 和 C#。
  • @Vlad:对于任意精度,它是 O((位数)^2),请参阅@Peters 答案的评论。
  • @ybungalobill:我不明白为什么这是真的。毕竟,这取决于 bigint 的内部表示。如果 bigints 由几个块组成(对应于表示 N = n_0 + 10^kn_1 + 10^2kn_2 等),则乘以 10 可以非常有效。你测量过 Python 解析的性能吗?
  • @Vlad:当您谈论这种转换时,您通常假设字符串 (10) 的基数与内部表示使用的基数不同。否则有可能使 O(1)。我们谈论的是复杂性,而不是性能。
【解决方案2】:

要转换为数字,您始终必须读取所有数字。所以至少是O(n)

现在做类似(伪代码)的事情

a = 0
foreach digit in string
do
   a = 10 * a + digit
end

O(n)。所以复杂度是O(n)

【讨论】:

  • 严格来说是错误的。对于O(n) 表示法,n 必须趋于无穷大。
  • @Vlad,如果使用任意精度数字,N 确实趋于无穷大。
  • @Charles:你是对的。因此,这仅对具有内置任意精度数字的语言有意义(不包括 C/C++ 和 C#)。
  • @Charles 和 @Vlad:但是对于任意精度,这变成了 O(n^2),因为计算乘法 10*a 是 O(n) 操作。
  • @larsmans:OP 谈到了内置转换。内置转换不能与非内置类型一起使用。 :-P
【解决方案3】:

数字字符串是以位置表示法格式化的数字 - 因此需要考虑每个数字乘以基数的幂的值,以便将数字转换为二进制格式。

是的,这是一个 O(N) 操作,因为运行时间会随着添加更多数字而线性增加。然而,实际上 N 可能会受到语言支持的任何数字数据类型的限制(例如 int32_t、int64_t)。但是,如果使用任意精度的数字类型(某些语言,如 Python,默认使用),那么位数没有限制(显然可用内存除外)。

【讨论】:

    【解决方案4】:

    我有理由确定,如果编码正确,处理纯数字运算符(在 c++ 和 c# 中,我认为它是“%”模运算符)会更有效,因为在某种程度上你必须检查类似的特征(结尾是否与开头匹配)以及执行字符串和数字之间的转换只会增加操作的复杂性,前提是您可以在不执行该转换的情况下执行相同的操作。

    也就是说,我不会担心在数字和字符串之间转换对性能的影响,因为与程序的大多数其他区域的性能影响相比,它可能微不足道。数值类型限制为 64 位,这对您可以计划解析的位数设置了相对较低的上限,除非您正在实现/使用自定义编码的大数类型。

    您不必担心复杂度是 O(n),其中 n 是数字的大小。它更像是 O(n),其中 n 是位数(我提到的低上限)或(如另一个回复中提到的)O(log(n)) 如果 n 是数字的大小。对性能的影响相对微不足道。

    现在,如果按照您的建议,您对 N 没有限制(这是不可能的,因为使用 2 GB 的 RAM,您最多只能存储 20 亿位数字),那么我们可能需要更多地考虑性能执行数学运算符。考虑“%”和“/”运算符在这种大数类型上的性能。但随后意识到,为了将数字转换为字符串,无论如何它基本上都使用相同的运算符。再一次,如果你做对了,你不能直接把它当作一个数字来处理。

    【讨论】:

      【解决方案5】:

      如果您将数字 N 转换为字符串。它需要以 10 为底的 O(log(N))。(如果除以 10 并保留余数) 如果要转换长度为 N 的字符串,则需要 O(N)。 (如果您使用不断添加到您的数字的算法 10^(N)*digit(N))

      如果你使用不属于你的函数(比如字符串),你只能期望它们会更慢。

      【讨论】:

      • 两者都取 O(N),其中 N 是位数。这是分析算术算法的正确方法。
      • 如果数字是N=10^5。将其转换为字符串需要多少步骤?我认为 O(log(N)),因为那是位数。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多