JavaScript正则表达式用于捕获十进制重复部分

3
寻找处理任意数字及其可能重复的小数部分的最佳方法,并发现其重复部分(如果有的话)。
最终,我需要使用横线符号(可以使用CSS文本修饰或MathML mline)装饰该数字,因此我需要知道重复开始的索引位置。
因此,我需要正则表达式来获取以下结果(或可用于算法中获取):
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

附加示例(来自评论):

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

3
你应该在例子列表中至少添加一个附加案例:"1.3333 // result: { "pattern": 3, index: 0}",因为下面很多答案都无法通过这个案例。(我假设你想要一个通用解决方案,而不仅仅是可以适用于某些数字的解决方案。) - Louis
4
你介意这种方法会错误地认为非循环小数(例如133/100——确切地说是1.33)的十进制表示是循环小数吗? - nobody
@AndrewMedico:一个非常好的观点。 - Matt Burland
4
像5/3这样的数字会被表示成1.66666667。 - Jonathan S.
@AndrewMedico - 不,这只是一个显示函数,如果客户端向其传递一个数字,则他们知道将得到什么返回。 - mtyson
5个回答

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

它的工作原理如下:
1、先将数字转换成字符串,以便使用正则表达式。
2、然后匹配此正则表达式:/\.(\d*?)(\d+)\2+$/
- \.匹配小数点。 - (\d*?)匹配小数点和循环节之间的数字,并将结果捕获到反向引用号1中。 - (\d+?)匹配循环节,并将其捕获到反向引用号2中。 - \2+匹配循环节的重复。 - $匹配字符串结尾。
3、最后,如果匹配是null(即没有匹配),返回null。否则,返回一个对象,其中包含将循环节(反向引用2)转换为数字的数量和小数点和循环节之间的数字的数量(反向引用1)。

谢谢Oriol,这真的让我朝着正确的方向开始了! - mtyson
这就是正确的做法! - tonix
不错...... - Cary Swoveland

6
你可以尝试这样做:

你可以试着这样操作:

(\d+?)\1+$

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

这个正则表达式匹配了一些数字,然后使用反向引用尝试立即匹配相同的数字集合1次或多次。它以字符串结尾为锚点,否则它会被以下情况所干扰:

1.5432121212

在这种情况下,重复的是数字21而不是12

将第一组添加?以使其成为非贪婪匹配,应该可以解决Louis提出的关于1.3333的问题。


是的,你肯定需要锚点。 - Cerbrus
@Cerbrus:同意。写完后我立刻注意到1.5432121212示例的问题。 - Matt Burland
@Louis:我更新了我的答案。 - Matt Burland
倒序输出单词非常聪明! - Cary Swoveland

3
你可以将此正则表达式与RexExp#exec一起使用,并在结果对象中使用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演示


@Louis: 匹配部分是 result[1] - anubhava
3
@anubhava:这个正则表达式是错误的,因为它需要从字符串的末尾捕获重复的数字。也就是说,它应该在1.3333中捕获3,但在1.3332中不捕获任何内容,因为1.3332不是循环小数 - Matt Burland
@MattBurland:感谢您的评论。不知何故,我在问题中忽略了“ending”部分。现已更正。 - anubhava

1

当输入为1.3333(有4位数字而不是3位)时会失败。它的结果是33而不是3 - Louis

0

就问题中提供的示例而言,接受的答案还可以。但是如果有一天你在这里找到自己所需的内容,那么你可能需要的正是主题所述的。

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

所以,你有一个字符串的浮点部分,想知道它是否重复。接受的答案在实践中失败了。你永远无法保证当重复部分结束时字符串也会结束。大多数情况下,字符串以重复部分的一部分结束,有时*由于双精度误差导致向不相关的数字跳跃并结束。因此,我的建议是:
/(\d+)\1+(?=\d*$)/g

现在这并不是银弹。它确实有帮助,但无法保护您免受像3.1941070707811985这样根本没有重复数字的吸血鬼的侵袭。要感受到它,您必须开发更深层次的机制。然而,在大多数情况下,它对于感知重复数字是完全可以胜任的。

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

在这种环境下,找到十进制浮点数的循环部分是否存在并不容易。您很可能需要对给定的字符串进行进一步处理,以及正则表达式的结果进行进一步简化/决策。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接