使用正则表达式如何从十进制数中删除尾随的零?

14

我需要编写一些正则表达式,以去掉小数点后面的尾随零。所使用的语言是Actionscript 3。因此,我想要编写:

var result:String = theStringOfTheNumber.replace( [ the regex ], "" );

例如:

3.04000 将变为 3.04

0.456000 将变为 0.456 等等。

我花了一些时间浏览各种正则表达式网站,发现这比我最初想象的要难解决。


将字符串转换为数字不会有帮助吗? - Duniyadnd
嗨Duniyadnd。我明白你这么说的原因。不幸的是,在大型浮点计算中,ActionScript 3对带有小数位的数字做了一些奇怪的处理。有些结果如果我们将其转换回数字,它会以浮点格式返回。 - user2190690
14个回答

20

正则表达式:

^(\d+\.\d*?[1-9])0+$

或者

(\.\d*?[1-9])0+$

替换字符串:
$1

演示

代码:

var result:String = theStringOfTheNumber.replace(/(\.\d*?[1-9])0+$/g, "$1" );

1
不知道用户输入是否以小数点开头。我也添加了这个答案。哦,这个也可以用.. ^(\d*\.\d*?[1-9])0+$ - Avinash Raj
感谢大家的回复。推荐的表达式似乎不能与ActionScript 3一起使用。这里写的任何表达式都可以翻译成适用于AS3的正则表达式解析器:http://www.regexr.com/ - user2190690
1
请看这里的演示效果:http://www.regexr.com/39mbd。如果您的正则表达式被双引号包含,则需要再次转义反斜杠,例如`(\\.\\d*?[1-9])0+$`。 - Avinash Raj
1
是的,用$1替换匹配的字符,在上面链接的底部查看替换。您可以通过replace函数仅去除尾随零。 - Avinash Raj
1
我发现这个程序在1.000000处出现了问题,但它仍然保持原样。将其设置为“^(\d+.\d*?[0-9])0+$”不会破坏任何其他用例,并将1.0000000修剪为1.0(您可以在上面链接的演示中尝试)。 - qwazix
显示剩余2条评论

9
我觉得最有效的方法是:
^([\d,]+)$|^([\d,]+)\.0*$|^([\d,]+\.[0-9]*?)0*$

例如,
s.replace(/^([\d,]+)$|^([\d,]+)\.0*$|^([\d,]+\.[0-9]*?)0*$/, "$1$2$3");

这将会发生变化。

1.10000 => 1.1
1.100100 => 1.1001
1.000 => 1
1 >= 1

1
感谢提供正则表达式。在我的所有情况中,您的实际上是最好的。但我认为有一个小问题:当替换例如“234.4500”时,它会再次返回零,因为末尾的数字范围包括零([0-9])。我认为它应该是 ^([\d,]+)$|^([\d,]+)\.0*$|^([\d,]+\.[1-9]*?)0*$ - Elias

6
如果在\b 边界后至少有一个数字,可以在去掉尾随零之前进行操作。
(\.\d+?)0+\b

并替换为第一个捕获组中捕获的内容。

$1

请参见regexr.com上的测试


这对我有效。一些输入: "纬度":19.4225447900000000,"经度":-99.2162050100000000 - Paul Vargas
如何使0数时,将其保留为两个零而不是一个? - jamesmpw
@jamesmpw 我猜你会把 0+ 改成 00+ - Jonny 5

3

2
其他答案没有考虑到没有小数部分的数字(如1.000000),或者使用了一个回顾函数(不幸的是,这个实现不支持)。因此,我修改了现有的答案。
  • 匹配使用^-?\d+(\.\d*[1-9])? - 演示(查看匹配)。这对于文本中的数字(如句子)将无效。
  • 替换(使用\1$1)使用(^-?\d+\.\d*[1-9])(0+$)|(\.0+$) - 演示(请参见替换)。如果删除^$,则该方法将适用于文本中的数字(如句子)。
两个演示均附有示例。 附注:如果必须,请用您使用的十进制分隔符替换\.(不需要斜杠),但我建议不要在此类正则表达式中支持多个分隔符格式(例如(\.|,))。内部格式通常使用一个特定的分隔符,如1.135644131中的(无需检查其他潜在分隔符),而外部格式则倾向于使用两个分隔符(一个用于小数,一个用于千位,如1.123,541,921),这将使您的正则表达式不可靠。
更新:我在两个正则表达式中添加了-?以支持负数,演示中没有。

1
我知道我有点晚了,但我认为这个问题可以用一种更简单的方法解决。除非我漏掉了什么或其他回复者过于复杂化,但我认为有一种更直接而且有弹性的解决方案。关于:
([0-9]*[.]?([0-9]*[1-9]|[0]?))[0]*

通过反向引用第一个组(\1),您可以获得没有尾随零的数字。
它也适用于.XXXXX...和...XXXXX.类型的数字字符串。例如,它将把.45600转换为.456,将123.转换为123。
更重要的是,它保留整数数字字符串(没有小数点的数字)。例如,它将把12300转换为12300。
请注意,如果有小数点并且小数点后只有零,则仅保留一个尾随零。例如,对于42.0000,您将得到42.0。
如果您想要消除前导零,则使用此RE(只需在前面放置[0]*):
[0]*([0-9]*[.]?([0-9]*[1-9]|[0]?))[0]*

1

我测试了排名靠前的几个答案:

^(\d+\.\d*?[1-9])0+$
(\.\d*?[1-9])0+$
(\.\d+?)0+\b

所有这些方法都无法处理小数点后面全是零的情况,比如 45.000 或者 450.000

修改后的版本可以匹配到这种情况: (\.\d*?[1-9]|)\.?0+$ 还需要将其替换为 '$1',如下所示:

preg_replace('/(\.\d*?[1-9]|)\.?0+$/', '$1', $value);

1

如果你的正则表达式引擎不支持“lookaround”功能,那么你可以使用这种简单的方法:

fn:replace("12300400", "([^0])0*$", "$1")

结果将是:123004。

0

0

虽然我来晚了,但这是我的解决方案:

(((?<=(\.|,)\d*?[1-9])0+$)|(\.|,)0+$)

我的正则表达式只匹配尾随的0,这样就可以很容易地进行.replaceAll(..)类型的函数。

分解一下,第一部分:((?<=(\.|,)\d*?[1-9])0+$)

  • (?<=(\.|,):一个积极的回溯。小数必须包含一个或一个,(在某些国家中,逗号被用作小数点)。但由于它是后向查找,因此不包括在匹配的文本中,但仍必须存在。
  • \d*?:懒惰地匹配任意数量的数字
  • [1-9]:匹配一个单个的非零字符(这将是尾随0之前的最后一个数字)
  • 0+$:匹配在最后一个非零数字和行结尾之间发生的1个或多个0

这对于尾随的0不是立即开始的情况非常有效,例如1.05.000。第二部分修复了这个问题:(\.|,)0+$

  • (\.|,):匹配一个.,,并将其包含在匹配的文本中。
  • 0+$:匹配小数点和行尾之间的1个或多个0

示例:

  • 1.0 变成 1
  • 5.0000 变成 5
  • 5.02394900022000 变成 5.02394900022

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