Ответ в теме: Преобразование строки в число на 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).