2016-12-25 126 views
2

稍短的版本正則表達式解析格式錯誤多項式

我使用這個正則表達式:

(^|[yY]\s{0,}\=|\+|\-)\s{0,}([0-9]{0,}\.?[0-9]{0,})\s{0,}(\*{0,1}[xX]{0,1})\s{0,}(\^{0,1})(-?)([0-9]{0,}\.?[0-9]{0,})(\s{0,}|$)? 

從方程式這樣的嘗試,並提取所有的元素係數和訂單編號:

y=x+3.3X^-50+ 15x25.5 - 4x^+2x^2 +3*x-2.5+1.1 

我想要正則表達式忽略錯誤的4x^這是缺少它的電源號碼(目前不這樣做)和讓我得到這個最終結果:

((1.0, 1.0), (3.3, -50.0), (15.0, 25.5), (2.0, 2.0), (3.0, -3.5), (1.1, 0.0)) 

其中第一個座標是係數,第二個是每個元素的順序。目前,如果我分別使用1 & 2和5 & 6來給出係數和順序,那麼'almost'上的正則表達式可以工作。

它只是在錯誤的4x^加上感覺非常不雅,但我在正則表達式有點小白,我不知道要做什麼改進。

如何提高這個表達式,並修復使4x^被認爲是「錯誤的」,但4x24x^2都好?

TL;博士版本

我試圖通過用戶爲了驗證,然後分解成方程一系列元素進入解析多項式方程。方程將以字符串形式呈現。

這裏的用戶是如何要求的格式字符串的例子:

y = 2.0x^2.5 - 3.1x + 5.2 

哪裏x是自變量(不是象徵倍),並y是因變量。

在現實中,用戶通常做任何下列錯誤:

  • 忘記包括y =
  • 添加*以係數如y = 2.0*x
  • 使用整數,而不是浮動,例如y = 5x
  • 設置順序時缺失^例如, y = x3
  • 添加或任何刪除空白

然而,對於所有的這些我會說,它仍然很容易理解用戶正在試圖寫。我的意思是顯而易見每個元素的係數和順序是什麼意思。

所以我想要做的是寫一些正則表達式,正確地將輸入的字符串分割成單獨的元素,並且可以得到我通常具有的元素的每個元素的A(係數)和B(順序) Ax^BAB可以各自是任何實數。

我設計了下面的例子:

y=x+3.3X^-50+ 15x25.5 - 4x^+2x^2 +3*x-2.5+1.1 

我相信這涵蓋了所有的我上面列出,除了另外一個直線上升的錯誤4x^+2x^2潛在的問題是缺少訂單元素4x^上。

對於此示例,我想要:((1.0, 1.0), (3.3, -50.0), (15.0, 25.5), (2.0, 2.0), (3.0, -3.5), (1.1, 0.0))其中4x^已被忽略。

我有些新的正則表達式,但我一直在使用regex101.com創建以下做出了努力:

(^|[yY]\s{0,}\=|\+|\-)\s{0,}([0-9]{0,}\.?[0-9]{0,})\s{0,}(\*{0,1}[xX]{0,1})\s{0,}(\^{0,1})(-?)([0-9]{0,}\.?[0-9]{0,})(\s{0,}|$)? 

這似乎近的工作,有以下問題:

  • 不不按上面給出的示例4x^捕獲缺失的訂單 - 我不確定如何在存在^時使訂單號的選擇性爲「有條件」,同時當^不存在但訂單號如y = 4x2
  • 極爲感覺在-簡潔/不雅,但作爲沒有經驗的我很努力,看看可以改進

同時請注意,我愉快地忽略與所述相同的順序重複元素的問題沒有被總結,例如我很高興忽略y = x^2 + x^2不出現爲y = 2x^2

謝謝你的幫助。

p.s.程序是用Go編寫的,但我也對Go有點不高興,因此我首先用Python進行原型設計。不知道這是否會對正則表達式產生任何影響(我真的很喜歡正則表達式)。

+0

我會注意到'{0,}'可以是'*','{0,1}'是'?'。 – Uriel

+0

我想你試圖得到的答案是((1.0,1.0),(3.3,-50.0),(15.0,25.5),(2.0,2.0),(3.0,-2.5),(1.1,0.0)) ...注意第五對是(3.0,-2.5)而不是(3.0,-3.5)。對? –

回答

0

下面的正則表達式將主要做:

(?P<c1>[+-]? *\d+(?:\.\d+)?)? *\*? *[xX] *(?:\^ *(?P<e1>-? *\d+(?:\.\d+)?)|(?P<e2>-? *\d+(?:\.\d+)?)?)|(?P<c2>[+-]? *\d+(?:\.\d+)?) 

我說,主要是因爲該解決方案採用了「4X ^」情況下,有秩序1,給出的要求已經相當寬鬆,否則試圖忽略這樣的術語使得RE變得更加複雜或者甚至不可能,因爲它造成了無法用RE解析的模糊性。

請注意缺席coeficients /指數將不會被捕獲爲您的示例結果中表示的'1.0',這將不得不在應用正則表達式並將所有空捕獲組作爲'1'(或' 0「代表指數取決於捕獲的組)。

Here you have the regex in regex101.com檢查/嘗試它是如何工作的。

在這裏,在golang工作程序,測試了幾個案例:

package main 

import (
    "fmt" 
    "regexp" 
    "strconv" 
    "strings" 
) 

const e = `(?P<c1>[+-]? *\d+(?:\.\d+)?)? *\*? *[xX] *(?:\^ *(?P<e1>-? *\d+(?:\.\d+)?)|(?P<e2>-? *\d+(?:\.\d+)?)?)|(?P<c2>[+-]? *\d+(?:\.\d+)?)` 

var cases = []string{ 
    "y=x+3.3X^-50+ 15x25.5 - 4x^+2x^2 +3*x-2.5+1.1", 
    "3.3X^-50", 
} 

func parse(d float64, ss ...string) float64 { 
    for _, s := range ss { 
     if s != "" { 
      c, _ := strconv.ParseFloat(strings.Replace(s, " ", "", -1), 64) 
      return c 
     } 
    } 
    return d 
} 

func main() { 
    re := regexp.MustCompile(e) 
    for i, c := range cases { 
     fmt.Printf("testing case %v: %q\n", i, c) 
     ms := re.FindAllStringSubmatch(c, -1) 
     if ms == nil { 
      fmt.Println("no match") 
      continue 
     } 
     for i, m := range ms { 
      fmt.Printf(" match %v: %q\n", i, m[0]) 
      c := parse(1.0, m[1], m[4]) 
      de := 1.0 
      if m[4] != "" { 
       de = 0.0 
      } 
      e := parse(de, m[2], m[3]) 
      fmt.Printf(" c: %v\n", c) 
      fmt.Printf(" e: %v\n", e) 
     } 
    } 
} 

,輸出:

testing case 0: "y=x+3.3X^-50+ 15x25.5 - 4x^+2x^2 +3*x-2.5+1.1" 
    match 0: "x" 
    c: 1 
    e: 1 
    match 1: "+3.3X^-50" 
    c: 3.3 
    e: -50 
    match 2: "+ 15x25.5" 
    c: 15 
    e: 25.5 
    match 3: "- 4x" 
    c: -4 
    e: 1 
    match 4: "+2x^2" 
    c: 2 
    e: 2 
    match 5: "+3*x-2.5" 
    c: 3 
    e: -2.5 
    match 6: "+1.1" 
    c: 1.1 
    e: 0 
testing case 1: "3.3X^-50" 
    match 0: "3.3X^-50" 
    c: 3.3 
    e: -50 

Here you have the program on golang playground嘗試。

+0

非常感謝你,這是我在聖誕節期間開展的一個小項目,只是決定回來 - 非常感謝幫助! – Chris