daydreamer
daydreamer

Reputation: 91959

Finding if Integer is Even or Odd

I am learning Erlang and one of the problems as per Joe's book states

The function even(X) should return true if X is an even integer and otherwise false. odd(X) should return true if X is an odd integer.

The way I solve this is

-module(math_functions).

%% API
-export([even/1, odd/1]).

even(Integer) -> (Integer >= 0) and (Integer rem 2 =:= 0).
odd(Integer) -> (Integer >= 1) and (Integer rem 2 =/= 0).

and run this as

Eshell V6.2  (abort with ^G)
1> math_functions:odd(13).
true
2> math_functions:odd(-13).
false
3> math_functions:odd(1).
true
4> math_functions:even(1).
false
5> math_functions:even(2).
true
6> math_functions:even(-2).
false
7>   

The question I have is if there are better ways to do this

Thanks

Upvotes: 2

Views: 4965

Answers (3)

subbu
subbu

Reputation: 11

Find the no if even 
%functions that manipulate functions are called higher-order %functions, and the data type that represents a function in Erlang is %called a fun. here in below example you see FUNCTIONS THAT HAVE %FUNCTIONS AS THEIR ARGUMENTS

% K is an example list
1> K=[4,5,6,8,10].  
[4,5,6,8,10]

% Use lisst:filter  to perform no/2  and filter if rem=0 
2> lists:filter(fun(J)->(J rem 2)=:=0 end, K).
[4,6,8,10]


Another way:

% Function to check even

22> Checkeven=fun(U)->(U rem 2)=:=0 end. 
#Fun<erl_eval.7.126501267>

23> Checkeven(5).
false

% Define a test list
25> K=[1,2,3,4,5].
[1,2,3,4,5]

% Use lists filter to apply Checkeven func to all elements of k

26> lists:filter(Checkeven,K). 

[2,4]


%Using List comprehension

42> K.
[1,2,3,4,5]

% For all elements of K check remainder of elem/2 is zero

43> [(S rem 2=:=0) || S<-K].
[false,true,false,true,false]

Upvotes: 0

Pascal
Pascal

Reputation: 14042

Answer to Daydreamer comment about Steve answer.

When you write a function, a frequent usage in erlang is to code only the "success" cases and let crash the unsuccessful cases (I'll come back later to explain why it is important).

Another criteria, valid for any language, is to avoid surprise when someone use or read your code.

In one of your comment you say that the odd and even functions you want to write are limited to positive or null integers (I won't discuss this choice, and at least the odd and even functions are limited to integers). This means that you have to ask yourself a first question: what is the behavior of my function if it is called with a bad parameter.

First choice: let it crash this the Steve proposition: the function works only with the correct arguments. I always prefer this solution. The only exception is if I do not master the input parameters, for example if they come directly from a file, a user interface ... Then I prefer the third choice.

Second choice: return a result this is your choice: you return false. From a logic point of view, for odd and even function, returning false is valid: is something is not true, it is false :o). I don't like this solution for 2 reasons. The first one is that it is not something you can generalize easily to something else than boolean answer. The second and more important to me, is that it may surprise the user. When the function odd(N) return false, it is reasonable to think that N is even, while in this case odd(-2) and even(-2) will both return false.

third choice: return a tagged result this is something you see very often in erlang: a function return either {ok,Value} or {Error,Term}. doing this you let the choice to the calling function to manage or not a bad arguments errors. the Error variable allows you to have explicit error messages, useful for debug and also user interface. In your example the code becomes:

even(X) when is_integer(X), X >= 0 -> {ok,(X band 1) == 0};
even(X) -> {illegal_param,X}.
odd(X) when is_integer(X), X >= 0 -> {ok,(X band 1) == 1};
odd(X) -> {illegal_param,X}.

When programming, it is important to detect error as soon as possible, in erlang it is even more important. If one process does not detect (and the simplest detection is crash) and error and propagate some invalid information through messages, it may be very difficult to find the root cause of a problem, ignoring which process (maybe died) issued this message. Coding only the success cases is an easy way to detect problems as soon as possible.

Upvotes: 3

Steve Vinoski
Steve Vinoski

Reputation: 20004

You could use guards to limit yourself to integers greater than or equal to zero, and then simply check the least-significant bit as suggested in the comment to your question. You can also define odd/1 in terms of even/1:

even(X) when X >= 0 -> (X band 1) == 0.
odd(X) when X > 0 -> not even(X).

The guards are part of the function-head, so if you call even(-1) it will fail to match in exactly the same way as if you called even(1, 2) (i.e. with the wrong number of arguments).

Upvotes: 7

Related Questions