2015-05-04 4 views
4

Как проверить десятичную точку, когда проверка строки является допустимым числом?Haskell: проверьте правильность строки.

Я думаю, что я использую что-то вроде следующего, но добавляю код для проверки десятичной точки!

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

В случае, если действительный номер определен в EBNF как:

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

Например, .5, 1.5, 1, 1. все действительные числа. + означает одно или несколько вхождений, а * обозначает ноль или более.

+2

Я бы рекомендовал использовать 'parsec' (или нечто подобное) для этого – Carsten

ответ

3

Взгляните на reads, то:

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

Может быть, есть лучший способ, хотя.

Обратите внимание, что это вернет True для номеров, которые считаются действительными в Haskell, ваш конкретный прецедент не полностью покрыт этим. Если вам нужен индивидуальный синтаксический анализ в соответствии с вашими спецификациями, вы должны использовать что-то вроде Parsec, как сказал в своем комментарии @ CarstenKönig.

+0

с помощью этого' IsNumber «1.0.» '(Или даже' 1.xxx ') тоже' True' - это действительно так? – Carsten

+0

почти ... try '" 1. "' или '. .5" 'now;) (все, что я хочу от вас, это проверить ваш код на спецификации: P - это действительно не так просто, как может показаться - но возможно, ** OP ** в порядке с этим) – Carsten

+1

Обратите внимание, что этот подход также будет принимать отрицательные числа и цифры в научном формате, например ' "1.3e5"'. – hammar

7

Вот простая стратегия:

  1. сдирать все цифры в начале строки.
  2. Оставшаяся строка должна теперь быть либо

    а) пустая строка или

    б) десятичную точку следуют все цифры.

Ну, почти. Это также будет соответствовать пустой строке "" и ".", но мы можем рассматривать их как особые случаи.

Перевод на Haskell:

isNumber :: String -> Bool 
isNumber "" = False 
isNumber "." = False 
isNumber xs = 
    case dropWhile isDigit xs of 
    ""  -> True 
    ('.':ys) -> all isDigit ys 
    _  -> False 
4

Простой подход включает в себя использование 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 
Смежные вопросы