2012-05-28 26 views
2

如何形成一個正則表達式,以匹配重複小數點中重複的唯一數字?Form Regex在重複小數內找到模式

目前我的正則表達式如下。

var re = /(?:[^\.]+\.\d*)(\d+)+(?:\1)$/; 

例子:

// Pass 
deepEqual(func(1/111), [ "0.009009009009009009", "009" ]); 

// Fails, since func(11/111) returns [ "0.099099099099099", "9" ] 
deepEqual(func(11/111), [ "0.099099099099099", "099" ]); 


現場演示這裏:http://jsfiddle.net/9dGsw/

這裏是我的代碼。

// Goal: Find the pattern within repeating decimals. 
// Problem from: Ratio.js <https://github.com/LarryBattle/Ratio.js> 

var func = function(val){ 
    var re = /(?:[^\.]+\.\d*)(\d+)+(?:\1)$/; 
    var match = re.exec(val); 
    if(!match){ 
     val = (val||"").toString().replace(/\d$/, ''); 
     match = re.exec(val); 
    } 
    return match; 
}; 
test("find repeating decimals.", function() { 
    deepEqual(func(1), null); 
    deepEqual(func(1/10), null); 
    deepEqual(func(1/111), [ "0.009009009009009009", "009" ]); 

    // This test case fails... 
    deepEqual(func(11/111), [ "0.099099099099099", "099" ], 
     "What's wrong with re in func()?"); 

    deepEqual(func(100/111), [ "0.9009009009009009", "009"]); 
    deepEqual(func(1/3), [ "0.3333333333333333", "3"]); 
}); 

回答

2

好的。採取喬爾的建議,我有點解決了我自己的問題。

問題在於正則表達式部分(\d+)+(?:\1)$與最接近字符串末尾的模式匹配,這使得它返回字符串「0.099099099099099」的「9」而不是「099」。

我克服這個問題的方法是將匹配長度設置爲2或更大,就像這樣。

(\d{2,})+(?:\1)$

並過濾結果與/^(\d+)(?:\1)$/,櫃面,一個圖案被卡住的圖案內。

下面是通過我所有測試用例的代碼。

現場演示:http://jsfiddle.net/9dGsw/1/

var func = function(val){ 
    val = (val || "").toString(); 
    var RE_PatternInRepeatDec = /(?:[^\.]+\.\d*)(\d{2,})+(?:\1)$/, 
     RE_RepeatingNums = /^(\d+)(?:\1)$/, 
     match = RE_PatternInRepeatDec.exec(val); 

    if(!match){ 
     // Try again but take off last digit incase of precision error. 
     val = val.replace(/\d$/, ''); 
     match = RE_PatternInRepeatDec.exec(val); 
    } 
    if(match && 1 < match.length){ 
     // Reset the match[1] if there is a pattern inside the matched pattern. 
     match[1] = RE_RepeatingNums.test(match[1]) ? RE_RepeatingNums.exec(match[1])[1] : match[1]; 
    } 
    return match; 
}; 

謝謝大家,幫助。

1

使用:var re = /^(?:\d*)\.(\d{1,3})(?:\1)+$/

我已經定義與循環小數的{MIN,MAX}最小/最大長度,因爲否則會009009009在第一測試情況下匹配也是如此。也許這還不是最終的解決方案,但至少有一個提示。

+1

它會更好地逃脫點,以使你的意圖匹配一個點(而不是任何東西)明確 –

+0

我已經糾正它。 –