Ошибка вычисления арифметического выражения

Я новичок в Erlang и пытаюсь создать простое приложение командной строки, в котором пользователь вводит ширину и высоту пола, стоимость квадратного фута пола, и им возвращается цена. По сути, я просто принимаю три целочисленных значения и возвращаю продукт.

23> c(costcalc).
{ok,costcalc}
24> costcalc:start().
Calculate the cost of flooring based on width, height, and cost per square foot.

Width in feet: 5
Height in feet: 5
Cost in dollars per square foot: $4
** exception error: an error occurred when evaluating an arithmetic expression in function  costcalc:start/0 (costcalc.erl, line 23)

Вот код, который я использую:

start() ->
  io:format("Calculate the cost of flooring based on width, height, and cost per square foot.\n"),
  W = string:to_integer(io:get_line("Width in feet: ")),
  H = string:to_integer(io:get_line("Height in feet: ")),
  C = string:to_integer(io:get_line("Cost in dollars per square foot: $")),
  Cost = W * H * C,
  io:fwrite(Cost).

Строка 23 - это Cost = W * H * C,, которая должна быть 100. Когда я запускаю 5 * 5 * 4. в оболочке напрямую, она вычисляется без проблем. Я также должен отметить, что это происходит независимо от того, использую ли я string:to_integer(), без которого, как мне кажется, я могу обойтись.

Что мне не хватает?


person Phillip Copley    schedule 07.08.2013    source источник
comment
Добавил проблему с io! вам не хватает формата ;)   -  person Khashayar    schedule 07.08.2013


Ответы (2)


Как упоминал @Khashayar, проблема в вашем коде заключается в том, что string:to_integer/1 возвращает пару (кортеж из двух элементов), а целое число является первым элементом.

Однако не следует использовать эту функцию. Строка в Erlang — это просто список целых чисел, и вы хотели использовать list_to_integer/1. Это распространенный способ преобразования строки в целое число.

Если бы вы использовали list_to_integer/1, вы бы избежали ошибки в @ Код Хашаяра, в котором второй элемент пары соответствует чему угодно. Действительно, вы можете ввести следующее:

Calculate the cost of flooring based on width, height, and cost per square foot. 
Width in feet: 1.9
Height in feet: 1.9
Cost in dollars per square foot: $ 4.9
4

Хотя 1.9*1.9*4.9 на самом деле равно 17.689.

К сожалению, не существует функции list_to_number/1, которая возвращала бы либо целое число, либо число с плавающей запятой. Самый распространенный способ справиться с этим — выполнить попытку/поймать с list_to_float/1 и вернуться к list_to_integer/1. В качестве альтернативы вы можете использовать io_lib:fread/2 или string:to_float/1, которые не вызывают исключений (тем не менее, как упоминалось выше, с использованием string:to_float/1 считается плохой практикой).

person Paul Guyot    schedule 07.08.2013
comment
Я не могу тестировать код еще несколько часов, но если кто-то использует list_to_float/1 и возвращает целое число, вызывает ли это исключение или это будет 1.0, 2.0 и т. д.? - person Phillip Copley; 07.08.2013
comment
list_to_float/1 определенно вызовет ошибку badarg при передаче строкового представления целого числа (например, "1"). Это задокументировано. - person Paul Guyot; 08.08.2013

у вас проблема со строкой: to_integer, она возвращает 2 значения! вы должны использовать их так.

start() ->
    io:format("Calculate the cost of flooring based on width, height, and cost per square foot.\n"),
    {W,_} = string:to_integer(io:get_line("Width in feet: ")),
    {H,_} = string:to_integer(io:get_line("Height in feet: ")),
    {C,_} = string:to_integer(io:get_line("Cost in dollars per square foot: $ ")),
    Cost = (W * H) * C,
    io:fwrite("~p~n",[Cost]).

Кстати, второе значение - это остальная часть строки,

to_integer(String) -> {Int, Rest} | {ошибка, причина}

удачи

person Khashayar    schedule 07.08.2013