Haskell:检查字符串是否为有效数字

14

如何在检查字符串是否为有效数字时检查小数点?

我想的是使用以下代码,但需要添加代码来检查小数点!

isNumber :: String -> Bool
isNumber xs = all isDigit xs || add extra code here

在EBNF中,有效数字被定义为:

number -> .digit+ | digit+ [ .digit*]
例如,.5,1.5,1,1. 都是有效的数字。+表示一个或多个出现,而*表示零个或多个。

2
我建议使用 parsec(或类似的工具)来完成这个任务。 - Random Dev
3个回答

17

一个简单的方法涉及使用readMaybe将字符串转换为数字。

import Text.Read

因此,用于检查它是否为Double的方法如下:

readMaybe "123" :: Maybe Double
Just 123.0

readMaybe "12a3" :: Maybe Double
Nothing

后者返回Nothing,这个字符串不是一个有效的数字。类似地,如果我们假设它是一个Int

readMaybe "12.3" :: Maybe Int
Nothing

9
以下是一种简单的策略:
1. 移除字符串开头的所有数字。 2. 剩下的字符串应该只包含以下两种情况之一: a) 空字符串,或 b) 一个小数点后跟着所有数字。
但实际上,这样也会匹配空字符串""和".",但我们可以将它们视为特殊情况。
在Haskell中的表示如下:
isNumber :: String -> Bool
isNumber ""  = False
isNumber "." = False
isNumber xs  =
  case dropWhile isDigit xs of
    ""       -> True
    ('.':ys) -> all isDigit ys
    _        -> False

3

请查看reads函数,然后:

isNumber :: String -> Bool
isNumber str =
    case (reads str) :: [(Double, String)] of
      [(_, "")] -> True
      _         -> False

也许有更好的方法。
请注意,这将对在Haskell中被视为有效的数字返回True,但你的特定用例并不完全覆盖此情况。如果你需要根据自己的规范进行自定义解析,建议使用像Parsec这样的工具,正如@CarstenKönig在他的评论中所建议的那样。

使用这个 isNumber "1.0."(甚至是 1.xxx)也是 True - 这是有效的吗? - Random Dev
现在尝试一下 "1."".5" 吧 ;) (我想要的只是让你根据规格测试你的代码 :P - 它可能并不像看起来那么简单 - 但也许 OP 对此很满意) - Random Dev
1
请注意,此方法还将接受负数和用科学计数法表示的数字,例如“1.3e5”。 - hammar
抱歉,EBNF 中有一个打字错误。第一部分应该是 .digit+ 而不是 :。有效数字需要能够以小数点开头! - Zast
如何修改代码,使输入为Char而不是String? - Alejandro Caro

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