【问题标题】:Are .NET's regular expressions Turing complete?.NET 的正则表达式图灵完备吗?
【发布时间】:2011-06-17 15:52:07
【问题描述】:

正则表达式通常被认为是不完善的语言的经典示例。例如,“正则表达式”作为这个 SO 问题looking for languages that are not Turing complete 的答案给出。

在我对转向完整性概念的理解中,这可能是一些基本的理解,这意味着不能使用正则表达式来检查“平衡”的模式。平衡的含义具有与结束字符相同数量的开始字符。这是因为这样做需要你有某种状态,以允许你匹配开始和结束字符。

然而,正则表达式的 .NET 实现引入了balanced group 的概念。此构造旨在让您回溯并查看之前的组是否匹配。这意味着一个 .NET 正则表达式:

^(?<p>a)*(?<-p>b)*(?(p)(?!))$

可以匹配以下模式:

ab
aabb
aaabbb
aaaabbbb
... etc. ...

这是否意味着.NET 的正则表达式是图灵完备的?或者是否还有其他缺少的东西需要语言是图灵完备的?

【问题讨论】:

  • 对,Turing Completeness的定义;-)
  • 好吧,我对这个有点兴奋,这实际上意味着它们可以匹配非常规语言,根据维基百科,这对于正则表达式语法并不少见。 “'正则表达式' [...] 与真正的正则表达式关系不大”:en.wikipedia.org/wiki/…
  • .NET 确实非常强大。它甚至具有可变长度后视功能。
  • 可变长度后视和前瞻对正则表达式没有任何作用。
  • @JustinMorgan:谈论一种语言的 power 通常意味着考虑需要什么样的自动机将语言与字符串匹配,以及带有前瞻/后视的正则表达式不需要比普通正则表达式更多的东西——DFA 或 NFA。您总是可以将带有环视的正则表达式重写为没有环视的正则表达式,但它可能会增长很多——带有环视的正则表达式比普通正则表达式更具表现力,因为它们允许您用少很多。 (匹配提取是另一回事 - 如果没有它们,您将无法获得与 "(?

标签: .net regex computer-science turing-machines turing-complete


【解决方案1】:

在计算理论中,正则表达式描述了一种正则语言。正则语言类正是那些可以被某种有限状态机识别或由正则文法生成的语言。但是,您描述的示例(平衡短语)不是常规语言,无法被有限状态机识别或由常规语法生成。事实上,这是所谓的上下文无关语言的教科书示例。这些需要下推自动机进行识别。上下文无关语言类是常规语言的超集,但也是图灵完备语言的真子集。大多数编程语言的语法(与语义相反)是一种上下文无关的语言。如果您有兴趣了解有关此主题的更多信息,可以从Chomsky hierarchy开始

【讨论】:

    【解决方案2】:

    .NET 中的正则表达式不是图灵完备的,因为它们总是停止。这对于一般的图灵机来说是不能这么说的。

    【讨论】:

    • 嗯嗯……真的吗?我确实遇到了一些,它们永远在执行。
    • 我相信一个相当愚蠢的引擎甚至可以通过a*+ 无限运行。
    • @SargeBorsch 听起来像一个正则表达式,输入大小的成本是指数级的。有一些众所周知且相当简单的模式会导致这种情况。 .NET 正则表达式引擎无法处理(其他一些引擎是)。没有实现所需的优化。我曾经研究过引擎内部结构,根据所采用的方法和代码,这对我来说似乎是个错误。
    【解决方案3】:

    你几乎错过了图灵完备的定义。

    图灵完备性,以艾伦命名 图灵的意义在于,每一个 计算的合理设计 可以模拟迄今为止先进的设备 通过通用图灵机——一个 观察已被称为 Church-Turing 论文。因此,一个 可以作为通用的机器 图灵机原则上可以 执行任何其他计算 可编程计算机能够。 然而,这与 编写程序所需的努力 对于机器,可能需要的时间 让机器执行 计算,或任何能力 机器可能拥有不相关的 计算。

    现在,你不能在正则表达式中做某些事情,所以语言不完整。

    你真的必须像其他人一样使用相同的定义,你知道的。有限的理解应该会触发发现真相。

    【讨论】:

    • 对。甚至没有远程“图灵完成”。您甚至无法使用正则表达式计算 1+1。
    • 谢谢你的回答,你的权利我混淆了为什么正则表达式不是图灵完备的反例与转向完整性的实际定义。在我的辩护中,提问是你学习东西的方式。
    • @罗伯特,对。唯一愚蠢的问题是让你离婚或在沙漠中赤身裸体,没有水的问题。
    【解决方案4】:

    @Inuyasha:其实你可以用正则表达式做加法。至少检查计算是否正确完成。唯一的事情是您必须以奇怪的顺序将输入提供给正则表达式(您不能使用正则表达式反转字符串(或检查它是否反转)。

    模式是:

    abc
    def
    ---
    ghi
    
    => cfi beh adg
    

    假设你想在二进制中添加 1011 和 0110:

    01011
    00110
    -----
    10001
    
    
    => 101 110 010 100 001
    

    如果你按照租约有效位到最大的顺序给出这个输入,穿插第一个操作数、第二个操作数和输出,你会得到字符串 101110010100001。这可以匹配

    ((000|011|101)|(110(010|100|111)*001))*
    

    这是一个花园品种正则表达式。您可以将其扩展到十进制加法,但正则表达式会变得非常复杂。

    【讨论】:

      猜你喜欢
      • 2011-12-20
      • 2010-09-20
      • 1970-01-01
      • 2014-12-26
      • 2015-08-23
      • 2011-05-22
      • 2017-02-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多