【问题标题】:Haskell: check if string is valid numberHaskell:检查字符串是否为有效数字
【发布时间】:2015-05-04 23:12:26
【问题描述】:

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

我在想的是我使用类似下面的东西,但是添加代码来检查小数点!

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

EBNF 中将有效数字定义为:

number -> .digit+ | digit+ [ .digit*]

例如,0.5、1.5、1、1. 都是有效数字。 + 表示出现一次或多次,* 表示出现零次或多次。

【问题讨论】:

  • 我建议为此使用parsec(或类似的东西)

标签: validation haskell


【解决方案1】:

一种简单的方法是使用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

【讨论】:

    【解决方案2】:

    这是一个简单的策略:

    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 - 这是有效的吗?
      • 几乎...现在尝试"1."".5" ;) (我想要的只是根据规范测试您的代码:P - 这真的不像看起来那么简单 -但也许 OP 对此没问题)
      • 请注意,这种方法也将接受负数和科学格式的数字,例如"1.3e5".
      • 抱歉,EBNF 中有错字。第一部分应该是 .digit+ 而不是 :。有效数字需要能够以小数点开头!
      猜你喜欢
      • 2013-02-13
      • 2016-01-15
      • 2018-06-15
      • 2019-05-05
      • 2019-10-04
      • 1970-01-01
      • 2021-10-03
      • 1970-01-01
      相关资源
      最近更新 更多