Ответ в теме: Преобразование строки в число на Prolog

      Комментарии к записи Ответ в теме: Преобразование строки в число на Prolog отключены
#2488

Алгоритм разбора числа должен отделять от строки символы и проверять являются ли они цифрой, поэтому пригодится функция для проверки цифр:

symbol_to_digit(DigitSymbol, Digit):-
  DigitSymbol >= 0'0, DigitSymbol =< 0'9,
  Digit is DigitSymbol - 0'0.

Тут 0'9 — это код цифры 9, такой вариант работает в SWI Prolog и многих других диалектах. Если в вашем диалекте такой синтаксис не поддерживается — можно использовать ASCII коды символов — 48 и 58 соответственно.

Наша функция должна принимать строку и возвращать первое число из нее и остаток строки.

get_positive(String, Number, TailString):-
  symbol_to_digit(HeadDigit, _Digit), !,
  get_positive(integral, 0, String, Number, TailString).

Мы вызываем вспомогательную функцию, при этом первый параметр integral означает, что сейчас вызываются правила считывания целой части, при этом начальное значение результата равно нулю.

Вспомогательная функция должна:

    • переходить на обработку дробной части если встречен символ точка, результат при этом формируется как сумма целой и дробной частей.
    • считывать первую цифру числа и добавлять ее к накопленному результату, умноженному на 10;
    • возвращать накопленный результат, если первый символ не является цифрой:

    get_positive(integral, IntegralPart, [0'.|Tail], Number, TailString):-
      !, get_positive(fraction, 0, 10, Tail, FractionPart, TailString),
      Number is IntegralPart + FractionPart.
    get_positive(integral, IntegralPart, [HeadDigit|Tail], Number, TailString):-
      symbol_to_digit(HeadDigit, Digit), !,
      TailIntegralPart is IntegralPart*10 + Digit,
      get_positive(integral, TailIntegralPart, Tail, Number, TailString).
    get_positive(integral, Number, String, Number, String):-!.

    При обработке дробной части очередная цифра числа должна делиться на множитель, изначально равный 10, но увеличивающий в 10 раз при каждой итерации. Первый символ, отличный от цифры будет означать, что число кончилось и нужно вернуть накопленный результат:

    get_positive(fraction, FractionPart, Factor, [HeadDigit|Tail], Number, TailString):-
      symbol_to_digit(HeadDigit, Digit), !,
      TailFractionPart is FractionPart + Digit/Factor,
      TailFactor is Factor*10,
      get_positive(fraction, TailFractionPart, TailFactor, Tail, Number, TailString).
    get_positive(fraction, Number, _TailFactor, String, Number, String).