Boolean true - positive 1 or negative 1?
Asked Answered
C

12

12

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?

Codie answered 7/4, 2009 at 19:13 Comment(0)
I
23

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
Illyria answered 7/4, 2009 at 20:23 Comment(3)
"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". That seems wrong. If 0 is defined as false and 1 is just the default value, wouldn't you have to test every bit anyway?Subtitle
Perhaps "default" is the wrong term. He's suggesting 1 as the SINGLE value for TRUE in this case, but also pointing out how "!= 0" has value.Christan
Niki, point taken - As Will indicates, I was suggesting that if you chose to enforce a "true" value, then you'd have to enforce it universally.Illyria
M
29

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.

Marita answered 7/4, 2009 at 19:17 Comment(8)
this also makes the language implementation easier and probably more efficient. true == !false that isBouffant
A fuzzy definition of true will bite you when you run into the misguided souls who write if(condition==true) ...Nyhagen
@Mark Ransom: It's not fuzzy at all. It is the set of everything that is not zero. That is a well-defined set.Marita
Fuzzy wasn't the right word; perhaps loose? If true isn't defined to be a single value, then comparing to "true" is asking for trouble, and there are people who have trouble understanding that.Nyhagen
@Mark Ransom: Which is why inherently comparing to true is a bad thing if the set of values that true and false can be represented in is more than two. .NET gets this right by explicitly creating a type for boolean values and limiting it to just TWO values. The same needs to be done here.Marita
I guess I'm used to C and C++. There's a boolean type in C++, but it isn't consistently used, and this problem crops up sometimes. And I think you understand my point: comparing to true is a bad thing.Nyhagen
@Mark Ransom: I'm in complete agreement. I always compare to "not false" for true conditions, unless I am in .NET.Marita
if (condition == true) works fine if your rules for comparison state that if a boolean exists on either side of the comparison operator, you must convert the other parameter to boolean. Thus "condition" would only be absolute_false or absolute_true when the == is evaluated.Uniformize
I
23

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
Illyria answered 7/4, 2009 at 20:23 Comment(3)
"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". That seems wrong. If 0 is defined as false and 1 is just the default value, wouldn't you have to test every bit anyway?Subtitle
Perhaps "default" is the wrong term. He's suggesting 1 as the SINGLE value for TRUE in this case, but also pointing out how "!= 0" has value.Christan
Niki, point taken - As Will indicates, I was suggesting that if you chose to enforce a "true" value, then you'd have to enforce it universally.Illyria
P
14

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)
Potto answered 7/4, 2009 at 19:33 Comment(2)
Some would argue that the fact that it continues to work in a somewhat less predictable way in the presence of a programming error is not a selling point.Lineup
Point taken, but in a weakly typed language you'd probably just get erroneous results the other way, without knowing it. Which do you prefer accidental correctness or intermittent, undetectable errors? Another reason to do TDD, I guess.Potto
D
11

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.

Dingus answered 7/4, 2009 at 19:23 Comment(6)
I agree. However Ada went a little overboard in my opinion.Separation
Internally they have to end up being 1,0 or otherwise... I can't think of any processors that can represent true/false without resorting to at least a binary flag. :-)Goldston
In my experience implicit conversions almost always lead to hard to understand convoluted sections of code. Even explicit conversions can cause issue. True is TRUE, false is FALSE. These Boolean values are not numbers.Pease
@Jim C - The problem is that at some level they have to become numbers on our common architectures...Goldston
Yes but fixating on this or leaking this abstraction can be the wrong choice depending on the aim of the language.Separation
True enough. This topic needs to be flagged "subjective and argumentative" :-)Goldston
B
5

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.

Benn answered 7/4, 2009 at 19:18 Comment(3)
+1 Good point - seeing a stack dump with 0xff as a parameter would tend to raise a red flag, and in this case would be a false positive for the programmer.Intellectualize
@Varkhan: It should be noted that VB went this way to define true as 0xFF and it was definitely more trouble than it was worth. Quite frankly, it's a horrible idea to define true in terms of an absolute value instead of a logic condition.Marita
@Varkhan: "that true=0x00, and any non-zero value is false" -- that's slightly inaccurate: A return value of 0 means "success", and other value are "error" codes. This is because there are many types of errors, but only one success. The fact that /bin/true returns 0 is an unfortunate side effect.Lineup
D
4

-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.

Dizzy answered 7/4, 2009 at 19:19 Comment(2)
the OP is asking about the internal representation and not how you type the value. For example in VB a truthy value is stored as -1 in memoryKinship
@Kinship yes, and my point was it is totally arbitrary. There is no "best" internal representation.Dizzy
G
3

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.

Godden answered 7/4, 2009 at 19:21 Comment(0)
F
3

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).

Fowliang answered 7/4, 2009 at 20:29 Comment(0)
B
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).

Bijugate answered 7/4, 2009 at 19:27 Comment(0)
I
1

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".

Indiscerptible answered 7/4, 2009 at 19:47 Comment(0)
L
1

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.

Leningrad answered 7/4, 2009 at 20:33 Comment(1)
Yes, see, for example, Logical AND in Forth?Lankton
B
0

The concept of non-zero values being treated as true is not a universal rule across all programming languages so that isn't obvious to me. It’s a convention used in some languages like C, but many others, including Pascal, Ada, Haskell, and even modern languages like Swift and Go, have strict Boolean types where only true or false are valid Boolean values.

When deciding on the internal representation of true in your language, consider the following:

  • 0x01 is simple and widely used, but it’s close to 0x00 (false), which could lead to errors if a bit is flipped.

  • 0xFF is more error-tolerant and distinct from 0x00, but it affects all bits, which might not be ideal for bitwise operations.

Consider your language’s goals and consistency with its design principles. Document your decision clearly for users. Remember, there’s no one-size-fits-all answer; it’s about what works best for your language’s philosophy and use cases.

Brinn answered 3/12, 2023 at 22:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.