简体   繁体   English

JavaScript 正则表达式捕获小数的重复部分

[英]JavaScript Regex to capture repeating part of decimal

Looking for the best way to take an arbitrary number with potentially repeating decimal part, and discover the repeating part (if present).寻找最佳方法来获取可能重复小数部分的任意数字,并发现重复部分(如果存在)。

Ultimately, I need to decorate the number with overline notation (either with css text-decoration or MathML mline), so I need to know the index of where the repetition begins also.最终,我需要用上划线符号(使用 css 文本装饰或 MathML mline)装饰数字,因此我还需要知道重复开始位置的索引。

So I need regex that will get me (or can be used in an algorithm to get) the following results:所以我需要正则表达式来获得(或可以在算法中使用以获得)以下结果:

1.333 // result: {"pattern": 3, index: 0}
1.5444 // result: {"pattern": 4, index: 1}
1.123123 // result: {"pattern": 123, index: 0}
1.5432121212 // result: {"pattern": 12, index: 4}
1.321 // result: null
1.44212 // result: null

Additional Example (from comments):附加示例(来自评论):

1.3333 // result: { "pattern": 3, index: 0}

You could try something like this: 你可以尝试这样的事情:

(\d+?)\1+$

http://regex101.com/r/eX8eC3/3 http://regex101.com/r/eX8eC3/3

It matched some number of digits and then uses a backreference to try and match the same set immediately afterwards 1 or more times. 它匹配了一些数字,然后使用反向引用尝试匹配相同的集合,然后立即进行1次或更多次。 It's anchored at the end of the string because otherwise it'll be tripped up by, for example: 它锚定在字符串的末尾,因为否则它会被绊倒,例如:

1.5432121212

It would see the 21 repeating instead of the 12 . 它会看到21重复而不是12

Adding ? 添加? to the first group to make it non-greedy should fix the problem with 1.3333 as raised by Louis. 第一组让它变得非贪婪应该解决路易斯提出的1.3333的问题。

function getRepetend(num) {
    var m = (num+'').match(/\.(\d*?)(\d+?)\2+$/);
    return m && {pattern: +m[2], index: m[1].length};
}

It works like this: 它的工作原理如下:

  • First, convert the number to string in order to be able to use regular expressions. 首先,将数字转换为字符串,以便能够使用正则表达式。
  • Then, match this regex: /\\.(\\d*?)(\\d+)\\2+$/ : 然后,匹配这个正则表达式:/ /\\.(\\d*?)(\\d+)\\2+$/
    • \\. matches the decimal dot. 匹配小数点。
    • (\\d*?) matches the digits between the decimal dot and the repetend, and captures the result into backreference number 1. (\\d*?)匹配小数点和重复之间的数字,并将结果捕获到反向引号1。
    • (\\d+?) matches the repetend, and captures it into backreference number 2. (\\d+?)匹配重复,并将其捕获到反向引号2。
    • \\2+ matches repetitions of the repetend. \\2+匹配重复的重复。
    • $ matches end of string. $匹配字符串的结尾。
  • Finally, if the match is null (ie there is no match), return null . 最后,如果匹配为null (即没有匹配),则返回null
  • Otherwise, return an object that contains the repetend (backreference 2) converted to number, and the number of digits between the dot and the repetend (backreference 1). 否则,返回包含转换为数字的重复(反向引用2)的对象,以及点与重复之间的数字位数(反向引用1)。

You can use this regex with RexExp#exec and use result.index in the resulting object: 您可以将此正则表达式与RexExp#exec使用, result.index在结果对象中使用result.index

var re = /(\d+)\1$/;
var s = '.5439876543212211211';

var result = re.exec( s );
console.log ( result.index );
//=> 14

console.log ( result[1] );
//=> 211

JsFiddle Demo JsFiddle演示

(.+)(?:\1)+$

Try this.See demo. 试试这个。看看演示。

http://regex101.com/r/uH3tP3/10 http://regex101.com/r/uH3tP3/10

The accepeted answer is OKish as per the given examples in the question are concerned.根据问题中给出的例子,接受的答案是好的。 However if one day you find yourself here what you probably need is exactly what the topic says.但是,如果有一天您发现自己在这里,您可能需要的正是主题所说的内容。

JavaScript Regex to capture repeating part of decimal JavaScript 正则表达式捕获小数的重复部分

So you have the floating part of a string and you want to know if it is repeating or not. 所以你有一个字符串的浮动部分,你想知道它是否重复。 The accepted answer fails in practice. 接受的答案在实践中失败了。 You can never guarantee that the string ends when the repeating part ends. 您永远无法保证字符串在重复部分结束时结束。 Most of the time the string ends with a portion of the repeating part or sometimes *thanks* to the double precision errors jumps to irrelevant figures towards the end. 大多数情况下,字符串以重复部分的一部分结尾,或者有时*感谢*双精度错误会跳转到末尾不相关的数字。 So my suggestion is 所以我的建议是
/(\d+)\1+(?=\d*$)/g

Now this is not a silver bullet.现在这不是灵丹妙药。 It's helpful but won't protect you from vampires like 3.1941070707811985 which happens to have no repetend at all.它很有用,但不会保护你免受像3.1941070707811985这样的吸血鬼的伤害,它恰好根本没有重复。 In order to feel it you have to develop deeper mechanisms.为了感受它,你必须发展更深层次的机制。 However in most cases it's just fine in percieving the repend like in但是在大多数情况下,像在

3.1941070707811985 // 07 which is wrong so prove it later 7.16666666810468 // 666 but reduce it to 6 later 3.00000000000001 // 000000 but reduce it to "" later 0.008928571428571428 // 285714 just fine, do nothing

It is not an easy task to find if the floating part of a decimal has repetends or not in this environment.在这种环境下查找小数的浮点部分是否重复不是一件容易的事。 Most possibly you need to do further processing on the given string and the result of the regex for futher reduction / decision.很可能您需要对给定的字符串和正则表达式的结果进行进一步处理,以进一步减少/决定。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM