When are booleans better than integers? - boolean

In most programming languages, 1 and 0 can be used instead of True and False. However, from my experience, integers seem to always be easier to use.
Here are some examples of what I mean:
if x is True: x = False
else: x = True
vs
x = abs(x-1)
__
if x is False: a = 0
else: a = 5
vs
a = 5*x
In what cases are booleans simpler/more efficient to use than 1 or 0?

You should always use any boolean built-in type for boolean values in high-level languages. Your second example would be a horror to debug in the case that x is true, but equal to a value different from 1, and a tricky one to figure out for any developer new to the code - especially one not familiar with your coding style.
What's wrong with
x = !x;
or
a = x ? 5 : 0;

One example where an integer could be more efficient than a boolean would be in a relational database. A bit column generally can't be indexed (I can't necessarily speak for all databases on that statement, hence "generally"), so something like a tinyint would make more sense if indexing is required.
Keep in mind that, depending on the use and on the system using it, while a boolean "takes less space" because it's just a single bit (depending on the implementation), an integer is the native word size of the hardware. (Certain systems likely use a full word for a boolean, essentially saving no space when it actually runs on the metal, just to use a simple word size.)
In high-level programming languages, the choice between a boolean and an int is really more of code readability/supportability than one of efficiency. If the values are indeed limited to "true" or "false" then a boolean makes sense. (Is this model in a given state, such as "valid," or is it not? It will never be a third option.) If, on the other hand, there are currently two options but there could be more someday, it might be tempting to use a boolean (even just "for now") but it would logically make more sense to use an int (or an enum).
Keep that in mind also when doing "clever" things in code. Sure, it may look sleeker and cooler to do some quick int math instead of using a boolean, but what does that do to the readability of the code? Being too clever can be dangerous.

For readibility and good intentions, it's always better to choose booleans for true/false.
You know that you have only two possible choices. With integers, things can get a bit tricky, especially if you're using 0 as false and anything else as true.
You can get too clever when using integers for true/false, so be careful.
Using booleans will make your intentions clearer to you 6 months later and other people who will maintain your code. The less brain cycles you have to use, the better.

I'd say in your examples that the boolean versions are more readable (at least as far as your intentions). It all depends on the context too. If you're sacrificing readability in an attempt to make micro optimizations, that's just evil.

I'm not sure about efficiency but I prefer booleans in many cases.
Your first example could be easily written as x = !x and x = abs(x-1) looks really obscure to me.
Also when using integers, you can't really be sure if x is 1 and not 2 or -5 or anything. When using booleans, it's always just true or false.

It's always more efficient to use Boolean because it's easier to process and uses less processing/memory. Whenever possible, use Boolean

Booleans obviously can only accept true/false or 0/1, not only that they use less processing power and memory as Webnet has already stated.

Performance points aside, I consider booleans and integers to be two fundamentally different concepts in programming. Boolean represents a condition, an integer represents a number. Bugs are easy to introduce if you don't strictly keep the value of your integer-boolean 0 or not 0, and why bother even with that when you can just use booleans, that allow for compile-time security / typechecking? I mean, take a method:
doSomething(int param)
The method alone does /not/ imply the param is interpreted as a boolean. Nobody will stop me from passing 1337 to it, and nobody will tell me what'll happen if I do - and even if it's clearly documented not to pass the 1337 value to the method (but only 0 or 1), I can still do it. If you can prevent errors at compile time, you should.
doSomething(bool param)
only allows two values: true and false, and neither are wrong.
Also, your examples about why integers would be better than booleans are kinda flawed.
if x is True: x = False
else: x = True
could be written as
x != x
whereas your integer alternative:
x = abs(x-1)
would require me to know:
What possible values x can have
what the abs() function does
why 1 is subtracted from x
what this actually /does/. What does it do?
Your second example is also a big wtf to me.
if x is False: a = 0
else: a = 5
could be written as:
a = (x) ? 5 : 0;
whereas your integer alternative
a = 5*x
again requires me to know:
What is X?
What can X be?
What happens if x = 10? -1? 2147483647?
Too much conditionals. Use booleans, for both readability, common sense, and bug-free, predictable code.

I love booleans, so much more readable and you've basically forced a contract with the user.
E.g. "These values are ONLY TRUE or FALSE".

Related

What is the correct way to select real solutions?

Suppose one needs to select the real solutions after solving some equation.
Is this the correct and optimal way to do it, or is there a better one?
restart;
mu := 3.986*10^5; T:= 8*60*60:
eq := T = 2*Pi*sqrt(a^3/mu):
sol := solve(eq,a);
select(x->type(x,'realcons'),[sol]);
I could not find real as type. So I used realcons. At first I did this:
select(x->not(type(x,'complex')),[sol]);
which did not work, since in Maple 5 is considered complex! So ended up with no solutions.
type(5,'complex');
(* true *)
Also I could not find an isreal() type of function. (unless I missed one)
Is there a better way to do this that one should use?
update:
To answer the comment below about 5 not supposed to be complex in maple.
restart;
type(5,complex);
true
type(5,'complex');
true
interface(version);
Standard Worksheet Interface, Maple 18.00, Windows 7, February
From help
The type(x, complex) function returns true if x is an expression of the form
a + I b, where a (if present) and b (if present) are finite and of type realcons.
Your solutions sol are all of type complex(numeric). You can select only the real ones with type,numeric, ie.
restart;
mu := 3.986*10^5: T:= 8*60*60:
eq := T = 2*Pi*sqrt(a^3/mu):
sol := solve(eq,a);
20307.39319, -10153.69659 + 17586.71839 I, -10153.69659 - 17586.71839 I
select( type, [sol], numeric );
[20307.39319]
By using the multiple argument calling form of the select command we here can avoid using a custom operator as the first argument. You won't notice it for your small example, but it should be more efficient to do so. Other commands such as map perform similarly, to avoid having to make an additional function call for each individual test.
The types numeric and complex(numeric) cover real and complex integers, rationals, and floats.
The types realcons and complex(realcons) includes the previous, but also allow for an application of evalf done during the test. So Int(sin(x),x=1..3) and Pi and sqrt(2) are all of type realcons since following an application of evalf they become floats of type numeric.
The above is about types. There are also properties to consider. Types are properties, but not necessarily vice versa. There is a real property, but no real type. The is command can test for a property, and while it is often used for mixed numeric-symbolic tests under assumptions (on the symbols) it can also be used in tests like yours.
select( is, [sol], real );
[20307.39319]
It is less efficient to use is for your example. If you know that you have a collection of (possibly non-real) floats then type,numeric should be an efficient test.
And, just to muddy the waters... there is a type nonreal.
remove( type, [sol], nonreal );
[20307.39319]
The one possibility is to restrict the domain before the calculation takes place.
Here is an explanation on the Maplesoft website regarding restricting the domain:
4 Basic Computation
UPD: Basically, according to this and that, 5 is NOT considered complex in Maple, so there might be some bug/error/mistake (try checking what may be wrong there).
For instance, try putting complex without quotes.
Your way seems very logical according to this.
UPD2: According to the Maplesoft Website, all the type checks are done with type() function, so there is rather no isreal() function.

Need an explanation for a confusing way the AND boolean works

I am tutoring someone in basic search and sorts. In insertion sort I iterate negatively when I have a value that is greater than the one previous to it in numerical terms. Now of course this approach can cause issues because there is a check which calls for array[-1] which does not exist.
As underlined in bold below, adding the and x > 0 boolean prevents the index issue.
My question is how is this the case? Wouldn't the call for array[-1] still be made to ensure the validity of both booleans?
the_list = [10,2,4,3,5,7,8,9,6]
for x in range(1,len(the_list)):
value = the_list[x]
while value < the_list[x-1] **and x > 0**:
the_list[x] = the_list[x-1]
x=x-1
the_list[x] = value
print the_list
I'm not sure I completely understand the question, and I don't know what programming language this is, but most modern programming languages use so-called short-circuit Boolean evaluation by default so that the logical expression isn't evaluated further once the outcome is known.
You can use that to guard against range overflow, like this:
while x > 0 and value < the_list[x-1]
but the check of x's range here must come before the use.
AND operation returns true if and only if both arguments are true, so if one of arguments is false there's no point of checking others as the final value is already known at that point. As for your example, usually evaluation goes from left to right but it is not a principle and it looks the language you used is not following that rule (othewise it still should crash on array lookup). But ut may be, this particular implementation optimizes this somehow (which IMHO is not good idea) and evaluates "simpler" things first (like checking if x > 0) before it look up the array. check the specs why this exact order works for you as in most popular languages you would still crash if test x > 0 wouldn't be evaluated before lookup

Boolean functions: if statements or simple return

I was checking a friend's code, and this pattern showed up quite a bit whenever he wrote functions that returned a boolean value:
def multiple_of_three(n):
if (n % 3) is 0:
return True
else:
return False
I maintain that it's simpler (and perhaps a bit faster) to write:
def multiple_of_three(n):
return (n % 3) is 0
Am I correct that the second implementation is faster? Also, is it any less readable or somehow frowned upon?
I very much doubt there is a compiler or interpreter still out there where there is a significant speed difference - most will generate exactly the same code in both situations. But your "direct return" method is, in my opinion, clearer and more maintainable.
I can't speak of the Python interpreter's exact behavior, but doing one way over another like that (in any language) simply for reasons of "faster" is misguided, and qualifies as "premature optimization". As Paul Tomblin stated in another answer, the difference in speed, if any, is quite negligible. Common practice does dictate, however, that the second form in this case is more readable. If an expression is implicitly boolean, then the if statement wrapper is frivolous.
See also http://en.wikipedia.org/wiki/Program_optimization#When_to_optimize
The second form is the preferred form. In my experience the first form is usually the sign of an inexperienced programmer (and this does not apply solely to Python - this crops up in most languages).

Methods of simplifying ugly nested if-else trees in C#

Sometimes I'm writing ugly if-else statements in C# 3.5; I'm aware of some different approaches to simplifying that with table-driven development, class hierarchy, anonimous methods and some more.
The problem is that alternatives are still less wide-spread than writing traditional ugly if-else statements because there is no convention for that.
What depth of nested if-else is normal for C# 3.5? What methods do you expect to see instead of nested if-else the first? the second?
if i have ten input parameters with 3 states in each, i should map functions to combination of each state of each parameter (really less, because not all the states are valid, but sometimes still a lot). I can express these states as a hashtable key and a handler (lambda) which will be called if key matches.
It is still mix of table-driven, data-driven dev. ideas and pattern matching.
what i'm looking for is extending for C# such approaches as this for scripting (C# 3.5 is rather like scripting)
http://blogs.msdn.com/ericlippert/archive/2004/02/24/79292.aspx
Good question. "Conditional Complexity" is a code smell. Polymorphism is your friend.
Conditional logic is innocent in its infancy, when it’s simple to understand and contained within a
few lines of code. Unfortunately, it rarely ages well. You implement several new features and
suddenly your conditional logic becomes complicated and expansive. [Joshua Kerevsky: Refactoring to Patterns]
One of the simplest things you can do to avoid nested if blocks is to learn to use Guard Clauses.
double getPayAmount() {
if (_isDead) return deadAmount();
if (_isSeparated) return separatedAmount();
if (_isRetired) return retiredAmount();
return normalPayAmount();
};
The other thing I have found simplifies things pretty well, and which makes your code self-documenting, is Consolidating conditionals.
double disabilityAmount() {
if (isNotEligableForDisability()) return 0;
// compute the disability amount
Other valuable refactoring techniques associated with conditional expressions include Decompose Conditional, Replace Conditional with Visitor, Specification Pattern, and Reverse Conditional.
There are very old "formalisms" for trying to encapsulate extremely complex expressions that evaluate many possibly independent variables, for example, "decision tables" :
http://en.wikipedia.org/wiki/Decision_table
But, I'll join in the choir here to second the ideas mentioned of judicious use of the ternary operator if possible, identifying the most unlikely conditions which if met allow you to terminate the rest of the evaluation by excluding them first, and add ... the reverse of that ... trying to factor out the most probable conditions and states that can allow you to proceed without testing of the "fringe" cases.
The suggestion by Miriam (above) is fascinating, even elegant, as "conceptual art;" and I am actually going to try it out, trying to "bracket" my suspicion that it will lead to code that is harder to maintain.
My pragmatic side says there is no "one size fits all" answer here in the absence of a pretty specific code example, and complete description of the conditions and their interactions.
I'm a fan of "flag setting" : meaning anytime my application goes into some less common "mode" or "state" I set a boolean flag (which might even be static for the class) : for me that simplifies writing complex if/then else evaluations later on.
best, Bill
Simple. Take the body of the if and make a method out of it.
This works because most if statements are of the form:
if (condition):
action()
In other cases, more specifically :
if (condition1):
if (condition2):
action()
simplify to:
if (condition1 && condition2):
action()
I'm a big fan of the ternary operator which get's overlooked by a lot of people. It's great for assigning values to variables based on conditions. like this
foobarString = (foo == bar) ? "foo equals bar" : "foo does not equal bar";
Try this article for more info.
It wont solve all your problems, but it is very economical.
I know that this is not the answer you are looking for, but without context your questions is very hard to answer. The problem is that the way to refactor such a thing really depends on your code, what it is doing, and what you are trying to accomplish. If you had said that you were checking the type of an object in these conditionals we could throw out an answer like 'use polymorphism', but sometimes you actually do just need some if statements, and sometimes those statements can be refactored into something more simple. Without a code sample it is hard to say which category you are in.
I was told years ago by an instructor that 3 is a magic number. And as he applied it it-else statements he suggested that if I needed more that 3 if's then I should probably use a case statement instead.
switch (testValue)
{
case = 1:
// do something
break;
case = 2:
// do something else
break;
case = 3:
// do something more
break;
case = 4
// do what?
break;
default:
throw new Exception("I didn't do anything");
}
If you're nesting if statements more than 3 deep then you should probably take that as a sign that there is a better way. Probably like Avirdlg suggested, separating the nested if statements into 1 or more methods. If you feel you are absolutely stuck with multiple if-else statements then I would wrap all the if-else statements into a single method so it didn't ugly up other code.
If the entire purpose is to assign a different value to some variable based upon the state of various conditionals, I use a ternery operator.
If the If Else clauses are performing separate chunks of functionality. and the conditions are complex, simplify by creating temporary boolean variables to hold the true/false value of the complex boolean expressions. These variables should be suitably named to represent the business sense of what the complex expression is calculating. Then use the boolean variables in the If else synatx instead of the complex boolean expressions.
One thing I find myself doing at times is inverting the condition followed by return; several such tests in a row can help reduce nesting of if and else.
Not a C# answer, but you probably would like pattern matching. With pattern matching, you can take several inputs, and do simultaneous matches on all of them. For example (F#):
let x=
match cond1, cond2, name with
| _, _, "Bob" -> 9000 // Bob gets 9000, regardless of cond1 or 2
| false, false, _ -> 0
| true, false, _ -> 1
| false, true, _ -> 2
| true, true, "" -> 0 // Both conds but no name gets 0
| true, true, _ -> 3 // Cond1&2 give 3
You can express any combination to create a match (this just scratches the surface). However, C# doesn't support this, and I doubt it will any time soon. Meanwhile, there are some attempts to try this in C#, such as here: http://codebetter.com/blogs/matthew.podwysocki/archive/2008/09/16/functional-c-pattern-matching.aspx. Google can turn up many more; perhaps one will suit you.
try to use patterns like strategy or command
In simple cases you should be able to get around with basic functional decomposition. For more complex scenarios I used Specification Pattern with great success.

Boolean true - positive 1 or negative 1?

I'm designing a language, and trying to decide whether true should be 0x01 or 0xFF. Obviously, all non-zero values will be converted to true, but I'm trying to decide on the exact internal representation.
What are the pros and cons for each choice?
It doesn't matter, as long as it satisfies the rules for the external representation.
I would take a hint from C here, where false is defined absolutely as 0, and true is defined as not false. This is an important distinction, when compared to an absolute value for true. Unless you have a type that only has two states, you have to account for all values within that value type, what is true, and what is false.
0 is false because the processor has a flag that is set when a register is set to zero.
No other flags are set on any other value (0x01, 0xff, etc) - but the zero flag is set to false when there's a non-zero value in the register.
So the answers here advocating defining 0 as false and anything else as true are correct.
If you want to "define" a default value for true, then 0x01 is better than most:
It represents the same number in every bit length and signedness
It only requires testing one bit if you want to know whether it's true, should the zero flag be unavailable, or costly to use
No need to worry about sign extension during conversion to other types
Logical and arithmetic expressions act the same on it
-Adam
Using -1 has one advantage in a weakly typed language -- if you mess up and use the bitwise and operator instead of the logical and operator, your condition will still evaluate correctly as long as one of the operands has been converted to the canonical boolean representation. This isn't true if the canonical representation is 1.
0xffffffff & 0x00000010 == 0x00000010 (true)
0xffffffff && 0x00000010 == 0xffffffff (true)
but
0x00000001 & 0x00000010 == 0x00000000 (false)
0x00000001 && 0x00000010 == 0xffffffff (true)
Why are you choosing that non-zero values are true? In Ada true is TRUE and false is FALSE. There is no implicit type conversion to and from BOOLEAN.
IMO, if you want to stick with false=0x00, you should use 0x01. 0xFF is usually:
a sign that some operation overflowed
or
an error marker
And in both cases, it probably means false. Hence the *nix return value convention from executables, that true=0x00, and any non-zero value is false.
-1 is longer to type than 1...
In the end it doesn't matter since 0 is false and anything else is true, and you will never compare to the exact representation of true.
Edit, for those down voting, please explain why. This answer is essentially the same as the one currently rated at +19. So that is 21 votes difference for what is the same basic answer.
If it is because of the -1 comment, it is true, the person who actually defines "true" (eg: the compiler writer) is going to have to use -1 instead of 1, assuming they chose to use an exact representation. -1 is going to take longer to type than 1, and the end result will be the same. The statement is silly, it was meant to be silly, because there is no real difference between the two (1 or -1).
If you are going to mark something down at least provide a rationale for it.
0xff is an odd choice since it has an implicit assumption that 8 bits is your minimum storage unit. But it's not that uncommon to want to store boolean values more compactly than that.
Perhaps you want to rephrase by thinking about whether boolean operators produce something that is just one 0 or 1 bit (which works regardless of sign extension), or is all-zeroes or all-ones (and depends on sign extension of signed two's-complement quantities to maintain all-ones at any length).
I think your life is simpler with 0 and 1.
The pros are none, and the cons are none, too. As long as you provide an automatic conversion from integer to boolean, it will be arbitrary, so it really doesn't matter which numbers you choose.
On the other hand, if you didn't allow this automatic conversion you'd have a pro: you wouldn't have some entirely arbitrary rule in your language. You wouldn't have (7 - 4 - 3) == false, or 3 * 4 + 17 == "Hello", or "Hi mom!" == Complex(7, -2).
I think the C method is the way to go. 0 means false, anything else means true. If you go with another mapping for true, then you are left with the problem of having indeterminate values - that are neither true nor false.
If this is language that you'll be compiling for a specific instruction set that has special support for a particular representation, then I'd let that guide you. But absent any additional information, for an 'standard' internal representation, I'd go with -1 (all 1's in binary). This value extends well to whatever size boolean you want (single bit, 8-bit, 16, etc), and if you break up a "TRUE" or a "FALSE" into a smaller "TRUE" or "FALSE", its still the same. (where if you broke a 16 bit TRUE=0x0001 you'd get a FALSE=0x00 and a TRUE=0x01).
Design the language so that 0 is false and non-zero is true. There is no need to "convert" anything, and thinking "non-zero" instead of some specific value will help you write the code properly.
If you have built-in symbols like "True" then go ahead and pick a value, but always think "non-zero is true" instead of "0x01 is true".
Whatever you do, once you select your values don't change them. In FORTH-77, true and false were defined as 1 and 0. Then, FORTH-83 redefined them as -1 and 0. There were a not few (well ok, only a few, this is FORTH we are talking about) problems caused by this.