Пролог средний список

У меня есть код, который может рассчитать среднее значение списка, но единственная проблема заключается в том, что он имеет ошибку, когда это пустой список. Я хочу вернуть false, когда список пуст. любой намек?

avg( List, Avg ):- 
    sum( List, Sum ),
    length( List, Length), 
    Avg is Sum / Length.

4 ответа

Просто добавьте условие, что список не пуст, например:

average( List, Average ):- 
    sum( List, Sum ),
    length( List, Length ),
    Length > 0, 
    Average is Sum / Length.

Это приведет к сбою предиката, что целесообразно, поскольку среднее значение не определено.

Конечно, деление на ноль обычно не допускается. Если (по соглашению) среднее из 0 элементов может быть 0, возможная коррекция будет

avg( List, Avg ):- 
    sum( List, Sum ),
    length( List, Length), 
    (  Length > 0
    -> Avg is Sum / Length
    ;  Avg is 0
    ).

редактировать, я тестировал в SWI-Prolog, заменяя sum/2 на sumlist/2

avg( List, Avg ):-
    sumlist( List, Sum ),
    length( List, Length),
    (  Length > 0
    -> Avg is Sum / Length
    ;  Avg is 0
    ).

тестовое задание:

?- avg([1,2,3],X).
X = 2.

?- avg([],X).
X = 0.

редактировать извините, я упустил из виду, что false требуется в пустом списке ввода. Тогда тест, если Length > 0 безусловно, уместно. Предикат потерпит неудачу в этом.

Альтернатива с использованием библиотеки (агрегат):

?- L=[1,2,3,4,5], aggregate((count,sum(N)),member(N,L),(Count,SumN)), Ave is SumN/Count.
L = [1, 2, 3, 4, 5],
Count = 5,
SumN = 15,
Ave = 3.

avg(список, Avg/1):-

sumlist( List, Sum ),

length( List, Length),

(  Length > 0
-> Avg is Sum / Length
;  Avg is 0
).  

Вы должны разделить среднее значение на 1., например, avg(List, Avg/1). Я просто скопировал его в комментариях выше и добавил avg/2.

Использование аккумулятора, то есть счетчика для вычисления среднего арифметического, может быть полезно для понимания того, как работает Prolog.

      mean([],0). % an empty list would have mean 0

mean(Xs,Mean):- % define the predicate with a list, and the mean output
  % pass the original list, mean output, and adds two counters
  % the counters should start at 0 for accumulation
  mean1(Xs,0,0,Mean). 

% base case, after recursion, the list would be empty
% the counter would accumulate the number of elements and
% the sum of the elements
mean1([],Count,Sum,Mean):- 
  Mean is Sum / Count.

% basic recursion to track the EleCount, plus 1 each time
% the Sum would add the X in the Xs each time, until Xs is empty
mean1([X|Xs],EleCount,Sum,Mean):-
  NewCount is EleCount + 1,
  NewSum is Sum + X,
  mean1(Xs,NewCount,NewSum,Mean).
Другие вопросы по тегам