验证输入字符串是否为有效的十进制数

3

有人能提供一个算法来检查输入的字符串是否为正确格式和形式的十进制数吗?

正确格式和形式的规则如下:

  1. 最多两位小数。
  2. 实际应用中,最大数字为99,999,999.99。
  3. 整数部分可以使用空格、逗号或点作为组分隔符。
  4. 小数部分可以使用逗号或点作为分隔符。

正确格式和形式的示例:

1,234,567.89   // 英式样式
1.234.567,89   // 法式样式
1 234 567,89   // 德式样式
1234567.89     // 数学英文样式
1234567,89     // 欧洲数学样式
12.00
12.0
12

请不要试图提出Decimal.Parse或Decimal.TryParse。这两种方法都会愉快地接受像“1,2,3,4”这样的字符串,这不是我想要的。


1
听起来你想写一个正则表达式。 - Lee Gunn
1
这些是“正确的形状和形式”的唯一示例吗? - Cody Gray
请你能定义一下规则吗?仅仅给出几个例子并不能构成一份规范。 - David Heffernan
3
截至目前为止,你应该已经接受了至少一个提问,因为已经有9个问题被提出了。 - David Heffernan
根据您的要求,1、2、3、4似乎是有效的。但我很惊讶解析方法没有遵守数字格式组大小。 - Stilgar
Stilgar --- 我可以无限地完善规则。我希望这些例子能够让聪明的读者了解所需的内容。 - user669226
3个回答

5

我在上周五回答了一个非常类似的问题, 而用于此的正则表达式将会比你想象的更加复杂。我强烈建议为每种样式设置单独的正则表达式,不是因为不能在一行中完成,而是因为这个一行代码将会很长,且难以维护。

以下是我会使用的模式:

English: ^[-+]?\d{1,3}(,\d{3})*(\.\d+)?$
French: ^[-+]?\d{1,3}(\.\d{3})*(,\d+)?$
German: ^[-+]?\d{1,3}(\s\d{3})*(,\d+)?$
English mathematical: ^[-+]?\d+(\.\d+)?$
European mathematical: ^[-+]?\d+(,\d+)?$

这些可以组合成类似于:
^[-+]?(\d{1,3}((,\d{3})*(\.\d+)?|([.\s]\d{3})*(,\d+)?)|\d+([,\.]\d+)?)$

希望这个一行代码对你来说足够可怕。这是一个非常常见、重要的任务,但它比看起来更加复杂。
在Rubular上使用您的示例输入进行测试:http://rubular.com/r/Dipvyrf6C8(请注意,我使组成为非捕获组以清晰显示结果)。 编辑:添加[-+]?条款以允许负数。

@justin morgan --- 短模式无法识别像“0.00”、“0.0”、“0,00”、“0,0”这样的字符串。这意味着小数点或逗号左侧只有一个数字。这个可以工作:“10.00”,“10,00”。 - user669226
@justin morgan --- 字符串如“0.00”,“0.0”,“0,00”,“0,0”。这意味着小数点或逗号左侧有一个或多个零。 - user669226
@justin morgan --- 这是一个非常糟糕的注释系统。无法编辑。无论如何,长模式的另一个问题是:像"0000,00"或"0000.00"这样的字符串。 - user669226
@user669226 - 目前长格式接受这些字符串作为数字,但如果您想要禁止它们,可以告诉我,我可以进行编辑。个人而言,我会保留它们,因为0000.00非常可能作为输入,并且它是正确的格式。 - Justin Morgan
@user669226 - 如我在另一个链接中提到的那样,之前的模式有意禁止了前导零。我进行了编辑,因为我更喜欢简单的形式,而且我觉得这样更正确。其他形式主要是为了展示如何禁止前导零,如果你想这样做的话。 请注意,现在将允许像00,123,456.789这样的数字,但我认为这是正确的行为。 - Justin Morgan


0
如果保证该数值一定含有小数部分,那么一种实现方法是:
var s = "1 334 567,80";
var decimalPart = s.Split(',', '.').Last();
var integerPart = s.Substring(0, s.Length - decimalPart.Length - 1);
integerPart = integerPart.Replace(",", string.Empty).Replace(".", string.Empty)
                         .Replace(" ", string.Empty);

var decimalValue = decimal.Parse(integerPart + "." + decimalPart,
                                 CultureInfo.InvariantCulture);

如果小数部分是可选的,我不确定您是否可以明确地解析此格式。

你的算法如何处理像“1,2,3,80”这样的字符串?你的算法是否认为该字符串是十进制数的有效表示? - user669226

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