<p>What I want to ask is not the <code>Boolean</code> value at the type level, but the <code>Boolean</code> value in actual implementation.</p>
<p>Because the actual register cannot store a bit, and the register has no type, we need to consider how to reinterpret the value according to the (user typed) <code>Boolean</code> type constraints when taking out the value in the register.</p>
<p>Most mainstream languages ​​continue the mathematical definition, assuming that 0 is false and other values ​​represent true.</p>
<p>Boolean values ​​are so commonly used that incorrect design may have disastrous consequences.</p>
<p>So question is: I want to know if there are any special troubles if I use a different definition (such as 0 represents <code>true</code> and 1 represents <code>false</code>)?</p>
<hr />
<p>Here are some opinions:</p>
<ul>
<li>Mathematics usually uses <code>0</code> to represent <code>false</code> and <code>1</code> to represent <code>true</code>
<ul>
<li>But mathematics does not consider the situation where there are other numbers</li>
</ul>
</li>
<li>Some mathematicians believe that <code>0</code> and <code>-1</code> should be used from the perspective of truth tables
<ul>
<li>I don't think negative numbers are a good idea, because there will be fatal problems when converting between signed and unsigned numbers.</li>
</ul>
</li>
<li>Some languages ​​only look at the last bit, if it is <code>0</code>, it means <code>false</code>, otherwise it means <code>true</code></li>
<li>The solution adopted by the shell is <code>0</code> to represent true and other values ​​to represent <code>false</code>
<ul>
<li>Because there is only one perfect success, and there are various failures</li>
</ul>
</li>
<li>...</li>
</ul>
<p>There are also some views from the computer perspective</p>
<ul>
<li>CPU initialization is all 0 initialization, 0 is the default value, the default value should be false
<ul>
<li>But if I set <code>true</code> as the default value, it seems that there will be no difference.</li>
</ul>
</li>
<li><code>eqz-jmp</code> is a common jump mode</li>
<li>Mainstream FFIs all default 0 to <code>false</code>
<ul>
<li>Indeed, there will be additional conversion loss at the FFI call site.</li>
<li>But FFI calls already have a lot of losses, and a normalization instruction is not fatal</li>
</ul>
</li>
</ul>

<booleans><registers>
Which number should be considered as true/false?
CC BY-SA 4.0
2024-05-26T17:04:55.913Z
I don't really understand your objections to -1. What are the "fatal problems" that you foresee? Can you give an example? Forth is a language that uses -1 for TRUE and it doesn't seem to cause any particular issues.
Nate Eldredge
CC BY-SA 4.0
2024-05-26T22:10:07.007Z
"*Because the actual register cannot store a bit*" - since you're talking about an actual implementation, which instruction set architecture are you talking about?
Bergi
CC BY-SA 4.0
2024-05-29T13:44:45.373Z
I would argue the "boolean" interpreted by the shell is the answer to the question "Was there an error (and what was it)?" so, although 0 means success and nonzero means failure, I wouldn't say "0 means true" and "nonzero means false".
Stef
CC BY-SA 4.0
2024-05-29T17:01:07.207Z
@stef: but "0 true and nonzero false" are how the control structures work (if, while, etc)
Nate Eldredge
CC BY-SA 4.0
2024-06-11T20:21:41.383Z
@Stef: I agree.  Perhaps the Unix developers confused things by having commands named `true` and `false` instead of `succeed` and `fail`.  Exit codes are *not* bools.
dan04
<p>As long as the code stays &quot;inside&quot; the type safe language you have created it does not really make much difference. In a fully type safe language there should be no way for the program to extract the actual representation. Each and every access to the boolean should pass through the type system which should protect the internal representation. There should be no type-unsafe conversions from/to boolean to say integer. Adding an integer and a boolean should either trigger a compilation error or trigger a type conversion with exact definition. C is notoriously bad when it comes to this, it is more or less an addition to the assembler. You are allowed to do a lot of not type-safe stuff with booleans, such as AND with a bit mask on a packed boolean bit field.</p>
<p>In theory your language could have different representations on different hardware platforms - the later stage of compilation will generally translate into actual hardware instructions (especially if the code is interpreted). This is possible as every translation to/from boolean should be type safe. It should not be possible to do an unsafe store of an integer into a boolean as one example.</p>
<p>The effect of the choice you make will show itself in some other areas. There could be a performance penalty on some CPU architectures depending on your choice. My personal guess is that the difference will be minute, but the only way to know is to measure the difference on larger actual software systems.</p>
<p>You also have to consider what happens when the boolean leaves the &quot;inside&quot; of the type controlled system. This can be when calling external code as in linking in external libraries. Other examples include storing data to external files or when interpreting data read from other programs.</p>
<p>So, it all boils down to your choices as language designer. You need to start on how you want the type conversions to work - what happens when you assign as example a real to a boolean? Should it be allowed and when should it translate into true/false.</p>
<p>One additional complication is if you want to add a &quot;not-a-boolean&quot; value to your type, as in the &quot;not-a-number&quot; we have for real values.</p>
<p>If you want my suggestion: do as others have done. Let 0 be false and anything else be true. When translating from boolean to other types, translate true to 1.</p>

CC BY-SA 4.0
2024-06-02T06:50:03.983Z
2024-06-02T06:50:03.983Z
ghellquist
<p>Logically, it doesn't matter which two values you take as long as your logical operations are programmed appropriately. Use bathroom sinks and kitchen sinks, for instance :-).</p>
<p>Physically, 0 (bit pattern 0…0) and -1 (bit pattern 1…1) result in the most stable storage under two assumptions: the two's complement representation is used, and the bits are stored independently. No memory can hide from the radiation of space completely; all DRAM modules (even with ECC) sooner or later experience bitflips (inevitably, incorrectable), even on the ground.</p>
<p>An example of a usage of 0 and -1 is SQL in MS Access: there, TRUE is -1, and FALSE is 0.</p>
<p>Two asides are worth being made.</p>
<p>First, you might also wonder about other pairs of bit patterns with the same maximal distance, say, 01010101 and 10101010 for 8-bit words. Then you'd have to use comparison with a constant instead of testing for the majority of zeros or ones. The the simple bitcount test (“does a given byte have at least 4 ones?”) would be replaced by the more complicated counting the number of positions with a deviation from one of the two constants (“does a given byte coincide with the constant on at least 4 positions?”). So I don't advise other bit patterns (unless there are other, independent reasons).</p>
<p>Second, as for the faults in rotational media and in transmissions over long distances, according to my own recollection, the bits need not be stored independently, the faults in them may be correlated, and bits may be skipped/inserted, so before changing your Boolean values to anything to increase tolerance to physical faults, take a look at the actual way the data is stored or transmitted in your application.</p>

CC BY-SA 4.0
2024-05-29T15:38:37.867Z
2024-05-31T21:55:32.160Z
2024-05-31T21:55:32.160Z
AlMa1r
CC BY-SA 4.0
2024-05-30T00:51:15.357Z
Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer).
Community Compiler
CC BY-SA 4.0
2024-05-30T01:20:04.097Z
I don't think a *citation* is necessary to establish that setting all 1 bits and all 0 bits makes the values maximally different in their representation, and thus "most stable".
Karl Knechtel
CC BY-SA 4.0
2024-05-30T02:47:11.473Z
If you use 0 for false and -1 for true, then a bitflip will give you some value that equals neither.  Say a bit is flipped in a 0 value and gives you 1024.  Do you treat that as false as well?  This suggests a convention where any value with the *majority* of bits set to 1 is treated as true, but that's going to be quite expensive to implement on a typical computer, especially if you don't have a hardware popcount instruction.  Do you know of any existing language or implementation where this is actually done?
Nate Eldredge
CC BY-SA 4.0
2024-05-30T02:48:29.683Z
Or do you treat 1024 as invalid, and insert frequent tests for such invalid values?
Nate Eldredge
CC BY-SA 4.0
2024-05-30T03:55:04.300Z
@KarlKnechtel: Well, but you can say the same of `0xDEADBEEF` and `0x21524110`, or any other two complementary values.  So 0 and -1 are at least not *unique* in this regard
Nate Eldredge
CC BY-SA 4.0
2024-05-30T12:30:35.543Z
@NateEldredge Clearly one needs to check whether the majority of bits is 1 or 0 and try to revive the value from that. I am unaware of programs doing this, but I've also not looked into the ***actual*** instructions in the code of the safety-critical or mission-critical programs (only experience through someone else), and these are the ones we should be looking at directly. I mean the program code running medical robots, controlling access to weapons, and stuff like that—there, the expense is justified and, depending on the purpose, a millisecond more might not matter.
AlMa1r
CC BY-SA 4.0
2024-05-30T12:50:46.010Z
If error-correction from cosmic ray bitflips is required, then it needs to be provided at the hardware level, not by the programming language for just one data type. Your argument that ECC memory alone cannot protect against all corruption, doesn't imply that we should implement redundant error-correction in software; that would still not protect against all corruption, for the same reason. Either way, you have to set a probability of failure low enough that you accept it. Then it makes much more sense to just choose ECC RAM which achieves that low probability.
kaya3
CC BY-SA 4.0
2024-05-30T20:50:36.713Z
@kaya3 ECC only lowers the rate of incorrectable bitflips and raises the chances of detecting bitflips. ECC does not fully avoid the bitflips (corrected or detected) completely, even on the ground. ECC also doesn't protect against many bits being flipped simultaneously without being detected (in my recollection, at least 3 per byte). As there is no absolute protection, if redundancy in software (in addition to proper hardware) helps and doesn't hurt too much, there's no reason not to do it. After all, the choice of ECC DRAM modules is limited, compared to the non-ECC DRAM.
AlMa1r
CC BY-SA 4.0
2024-05-30T21:07:19.330Z
@kaya3 As for the other datatypes, you should, ideally, consider them too. There is no limit to perfection. Boolean values are used to guide the control flow (say, turn the engines on/off or check whether they are on/off), which is often more important than data (say, telemetry). So if any datatype should be considered to be hardened against physical faults at all at a low cost, Bool would be a good start. Frankly, I don't feel comfortable talking in general, about all code. We should start by inspecting a tiny real-world example of machine code in a safety- or mission-critical application.
AlMa1r
CC BY-SA 4.0
2024-05-31T11:10:26.380Z
*"As there is no absolute protection, if redundancy in software (in addition to proper hardware) helps and doesn't hurt too much, there's no reason not to do it."* Adding better error correction in hardware is better than adding redundant error correction in software. When you are already using error correcting codes in hardware, it is not *a priori* true that the most likely error to go uncorrected by the hardware is a single bit flip ─ as such, you don't generally get the combined value of two error-correcting codes when you use them together.
kaya3
CC BY-SA 4.0
2024-05-31T11:12:22.077Z
Also, booleans used for control flow tend to be retained in the register for a very short time (they are typically computed and then consumed by the next instruction), so there is practically no opportunity for them to become corrupted while they are stored anywhere. In short, what you're proposing in this answer is not a solution to a real problem, and if the problem were real, then this wouldn't be a good solution to it.
kaya3
CC BY-SA 4.0
2024-05-31T21:38:13.943Z
@kaya3 No, adding hardware error correction is NOT ALWAYS better than adding software error correction. (Note that these two kinds are complementary, so comparing them is partially meaningless.) If your DRAM stores magnitudes less of control bits than of data bits with inherent inaccuracies (photos, video, or audio) or that is short lived (weather), adding hardware error correction would spend precious resources MOSTLY on stuff not worth it. Your software might even run on a not easily replaceable non-ECC memory or an apriori unknown memory type, so you might not even have a choice here.
AlMa1r
CC BY-SA 4.0
2024-05-31T21:38:24.160Z
@kaya3 No, Booleans are stored not only in registers, but also in the volatile main memory. Also in the caches of long-term–storage media. (Also in the storage itself, though the bits are stored there not necessarily independently, so you'd need to look carefully into the storage implementation before taking this into account. The rotational storages have hardware error correction usually built in anyway and already heavily rely on it.) In short, what you're proposing in your comments is an invalid argument and eristic in any case.
AlMa1r
CC BY-SA 4.0
2024-05-31T22:23:39.370Z
**Comments have been [moved to chat](https://chat.stackexchange.com/rooms/153426/discussion-on-answer-by-alma1r-which-number-should-be-considered-as-true-false); please do not continue the discussion here.** Before posting a comment below this one, please review the [purposes of comments](/help/privileges/comment). Comments that do not request clarification or suggest improvements usually belong as an [answer](/help/how-to-answer), on [meta], or in [chat]. Comments continuing discussion may be removed.
lyxal
<p>Using a unique Boolean definition, where zero represents actual and 1 represents false, can introduce confusion and workable blunders in code interpretation, especially when participating with others or using libraries that observe the traditional definition. It may also lead to surprising behaviors and make code tougher to recognize and maintain. Therefore, deviating from the fashionable Boolean definition can cause compatibility problems and increase the threat of bugs in software program development.</p>

CC BY-SA 4.0
2024-06-01T14:19:39.990Z
2024-06-01T14:19:39.990Z
spammer
CC BY-SA 4.0
2024-06-02T18:46:05.753Z
Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer).
Community Compiler
<p>I think your question is a false dichotomy, at least in a lot of cases; modern high-level languages<sup>1</sup> tend not to allow conversion between booleans and integer types, so this should be considered an implementation detail and it doesn't matter how a specific implementation happens to do it. Taking this further, &quot;register&quot; is an implementation detail as well.</p>
<p><sup>1. C and C++ are not &quot;modern&quot; in this context!</sup></p>

CC BY-SA 4.0
2024-05-26T11:07:14.537Z
2024-05-26T11:07:14.537Z
Philip Kendall
CC BY-SA 4.0
2024-05-26T11:12:39.370Z
What languages *do* you consider to be modern and high level? I can't think of any mainstream ones that don't have `true + 1 = 2` except maybe Rust. Though I don't really know any functional languages so maybe it's more common in that field
mousetail 'he-him'
CC BY-SA 4.0
2024-05-26T11:15:35.603Z
None of Java, C# nor Go will allow that!
Philip Kendall
CC BY-SA 4.0
2024-05-26T15:59:39.383Z
@mousetail In general, it seems like there is a significant push for statically typed languages to move more and more towards type safety (which would usually prevent that).
David Young
CC BY-SA 4.0
2024-05-26T22:07:02.207Z
@mousetail Even if you want to allow that, you can compile it as `to_int(true) + 1` and use any internal arbitrary representation for your booleans
Bergi
CC BY-SA 4.0
2024-05-27T22:23:14.457Z
PHP and Python both allow it. In Python, `bool` is a subtype of `int`. Whatever your personal preferences may be, these are two of the most popular high-level languages these days.
Barmar
CC BY-SA 4.0
2024-05-30T08:50:53.470Z
@Barmar That's a fair point. However given that (at least to my understanding) dynamically typed languages have to box every variable anyway, the actual register representation and any performance concerns are much less relevant there.
Philip Kendall
CC BY-SA 4.0
2024-06-07T16:35:56.407Z
JavaScript also has `true + 1 == 2`.  Of course, JavaScript is famously loose with type conversions.
dan04
CC BY-SA 4.0
2024-06-11T01:13:33.787Z
@PhilipKendall, the interesting question isn't "does the language allow `true + 1`?", the interesting question is "does the language allow `if(n + 3)`?".
Mark
<blockquote>
<p>Because the actual register cannot store a bit, and the register has no type,</p>
</blockquote>
<p>You are probably thinking about a general purpose register. However, CPUs typically also have flags to store certain results, and those flags are typically one bit containing a true/false value. Many CPU architectures have something like a <code>CMP</code> (compare) instruction, which can compare two values for equality, and which stores the result in one of those flags. Some CPUs allow those flags to be accessed directly, some only indirecly (like with <code>JE</code>/<code>JNE</code> (jump if equal/not equal) instructions), and some present a collection of flags as a single status register. Still, you can think of the flag as a single boolean register.</p>
<p>It's also not right to say that register don't have a type. You typically have different types of registers, some for integers, some for floating points. In hardware, there is typically a set of registers that are all 32 or 64 bits, but the instruction set might expose logical registers that are 8 or 16 bits wide. At the hardware level there are also no ones and zeroes, it's some amount of charge or voltage, or the absence of it, and it doesn't even have to be that a high voltage means a 1.</p>
<blockquote>
<p>Mathematics usually uses 0 to represent <code>false</code> and 1 to represent <code>true</code></p>
</blockquote>
<p>I think it's computer science that does that, not mathematics.</p>
<blockquote>
<p>Some mathematicians believe that 0 and -1 should be used from the perspective of truth tables</p>
</blockquote>
<p>Some operations on booleans have an equivalent in operations on integers. For example, if you use 0 for false and 1 for true, then a logical AND is equivalent to multiplication of those integer values. You can then also see that this no longer works if you use 0 for true and 1 for false.</p>
<p>When working with registers of a fixed width, you are working in a ring with modular arithmetic, and usually signed numbers are stored in <a href="https://en.wikipedia.org/wiki/Two%27s_complement" rel="nofollow noreferrer">two's complement</a>. That means -1 is equivalent to all bits in that register being 1. This can make some things easier, for example in the following piece of C code:</p>
<pre class="lang-c prettyprint-override"><code>bool a = …;
int x = 123;
int y = a ? x : 0;
</code></pre>
<p>The compiler could then replace the conditional expression with a bitwise AND operation:</p>
<pre class="lang-c prettyprint-override"><code>int y = x &amp; (int)a;
</code></pre>
<p>Which could result in much faster assembly being generated. However, since using just 1 and 0 for true and false is so common, most CPUs provide instructions to handle that as fast as storing booleans as -1 and 0 would.</p>
<p>Also, note that in C and languages that use the same ABI, 0 is <code>false</code> but when converting an <code>int</code> or other similar type to <code>bool</code>, any non-zero value is considered <code>true</code>. And while the ABI says that a boolean is stored or passed as a parameter, the value should be exactly 1 or 0, the compiler is allowed to do anything it wants behind the scenes as long as the observable end result is the same as what the language specification says. So it might actually store <code>true</code> as a non-zero value other than 1 if that is more expedient and nothing would break.</p>
<blockquote>
<p>The solution adopted by the shell is <code>0</code> to represent <code>true</code> and other values ​​to represent <code>false</code></p>
</blockquote>
<p>Not exactly; the result of a command is not a boolean, it is an error code, where 0 means no error. The same goes for <a href="https://en.cppreference.com/w/c/error/errno" rel="nofollow noreferrer"><code>errno</code></a>.</p>
<blockquote>
<p>Mainstream FFIs all default 0 to <code>false</code></p>
</blockquote>
<p>Because C defined <code>false</code> to be zero, and most FFIs use C's ABI.</p>
<blockquote>
<p>CPU initialization is all 0 initialization,</p>
</blockquote>
<p>Not necessarily, and especially not the memory. A BIOS or operating system's first task is usually to zero all memory. The CPU has defined reset values for some of the registers, and some of those reset values might not be zero. When a program is started by the operating system, it's also not the case that all registers are zero.</p>
<p>What is true is that often the CPU provides a fast way to set a register to zero, either by having specific instructions for that or by having a special register that is always zero, and that you can copy into other registers. And even if there is nothing explicit, you can almost always XOR a register with itself.</p>

CC BY-SA 4.0
2024-05-26T12:18:28.960Z
2024-05-26T22:07:15.667Z
2024-05-26T22:07:15.667Z
G. Sliepen
CC BY-SA 4.0
2024-05-26T17:10:14.703Z
Actually, many if not all C and C++ ABIs specify that `bool` values must be passed and stored as 0 or 1, nothing else. This allows functions to use bitwise operations on `bool` inputs without spending extra instructions to coerce to 0/1. Of course this is unrelated to the language semantics that nonzero values of *other* types are "truthy".
Nate Eldredge
CC BY-SA 4.0
2024-05-26T17:16:19.437Z
Thanks to de Morgan's law, if we take 0 for true and 1 for false, we can still use bitwise logic instructions to do Boolean logic: now boolean AND corresponds to bitwise OR, and vice versa.
Nate Eldredge
CC BY-SA 4.0
2024-05-26T17:41:41.160Z
I should rephrase that. While I know the ABI says `bool` must be passed as 0 or 1, the as-if rule applies as well; if the compiler can see how and where things are passed, it can do things differently behind the scenes, as long as the end result is the same. And when converting an `int` to a `bool` for example, any non-zero value `int` value becomes `true`.
G. Sliepen
# Which number should be considered as true/false?
Posted by: username_0 on 2024-05-26
What I want to ask is not the `Boolean` value at the type level, but the `Boolean` value in actual implementation.

Because the actual register cannot store a bit, and the register has no type, we need to consider how to reinterpret the value according to the (user typed) `Boolean` type constraints when taking out the value in the register.

Most mainstream languages ​​continue the mathematical definition, assuming that 0 is false and other values ​​represent true.

Boolean values ​​are so commonly used that incorrect design may have disastrous consequences.

So question is: I want to know if there are any special troubles if I use a different definition (such as 0 represents `true` and 1 represents `false`)?

---

Here are some opinions:

* Mathematics usually uses `0` to represent `false` and `1` to represent `true`
  + But mathematics does not consider the situation where there are other numbers
* Some mathematicians believe that `0` and `-1` should be used from the perspective of truth tables
  + I don't think negative numbers are a good idea, because there will be fatal problems when converting between signed and unsigned numbers.
* Some languages ​​only look at the last bit, if it is `0`, it means `false`, otherwise it means `true`
* The solution adopted by the shell is `0` to represent true and other values ​​to represent `false`
  + Because there is only one perfect success, and there are various failures
* ...

There are also some views from the computer perspective

* CPU initialization is all 0 initialization, 0 is the default value, the default value should be false
  + But if I set `true` as the default value, it seems that there will be no difference.
* `eqz-jmp` is a common jump mode
* Mainstream FFIs all default 0 to `false`
  + Indeed, there will be additional conversion loss at the FFI call site.
  + But FFI calls already have a lot of losses, and a normalization instruction is not fatal
**Tags:** booleans registers
> **Comments:**
> **username_1**: I don't really understand your objections to -1. What are the "fatal problems" that you foresee? Can you give an example? Forth is a language that uses -1 for TRUE and it doesn't seem to cause any particular issues.  
> **username_2**: "*Because the actual register cannot store a bit*" - since you're talking about an actual implementation, which instruction set architecture are you talking about?  
> **username_3**: I would argue the "boolean" interpreted by the shell is the answer to the question "Was there an error (and what was it)?" so, although 0 means success and nonzero means failure, I wouldn't say "0 means true" and "nonzero means false".  
> **username_1**: @stef: but "0 true and nonzero false" are how the control structures work (if, while, etc)  
> **username_4**: @Stef: I agree.  Perhaps the Unix developers confused things by having commands named `true` and `false` instead of `succeed` and `fail`.  Exit codes are *not* bools.  
---
## 5 answers
### Answer by username_12 on 2024-05-26. Score: 11
I think your question is a false dichotomy, at least in a lot of cases; modern high-level languages1 tend not to allow conversion between booleans and integer types, so this should be considered an implementation detail and it doesn't matter how a specific implementation happens to do it. Taking this further, "register" is an implementation detail as well.

1. C and C++ are not "modern" in this context!
> **Comments:**
> **username_13** (2024-05-26): What languages *do* you consider to be modern and high level? I can't think of any mainstream ones that don't have `true + 1 = 2` except maybe Rust. Though I don't really know any functional languages so maybe it's more common in that field  
> **username_12** (2024-05-26): None of Java, C# nor Go will allow that!  
> **username_14** (2024-05-26): @mousetail In general, it seems like there is a significant push for statically typed languages to move more and more towards type safety (which would usually prevent that).  
> **username_2** (2024-05-26): @mousetail Even if you want to allow that, you can compile it as `to_int(true) + 1` and use any internal arbitrary representation for your booleans  
> **username_15** (2024-05-27): PHP and Python both allow it. In Python, `bool` is a subtype of `int`. Whatever your personal preferences may be, these are two of the most popular high-level languages these days.  
> **username_12** (2024-05-30): @Barmar That's a fair point. However given that (at least to my understanding) dynamically typed languages have to box every variable anyway, the actual register representation and any performance concerns are much less relevant there.  
> **username_4** (2024-06-07): JavaScript also has `true + 1 == 2`.  Of course, JavaScript is famously loose with type conversions.  
> **username_16** (2024-06-11): @PhilipKendall, the interesting question isn't "does the language allow `true + 1`?", the interesting question is "does the language allow `if(n + 3)`?".  
---
### Answer by username_17 on 2024-05-26. Score: 6
Because the actual register cannot store a bit, and the register has no type,

You are probably thinking about a general purpose register. However, CPUs typically also have flags to store certain results, and those flags are typically one bit containing a true/false value. Many CPU architectures have something like a CMP (compare) instruction, which can compare two values for equality, and which stores the result in one of those flags. Some CPUs allow those flags to be accessed directly, some only indirecly (like with JE/JNE (jump if equal/not equal) instructions), and some present a collection of flags as a single status register. Still, you can think of the flag as a single boolean register.
It's also not right to say that register don't have a type. You typically have different types of registers, some for integers, some for floating points. In hardware, there is typically a set of registers that are all 32 or 64 bits, but the instruction set might expose logical registers that are 8 or 16 bits wide. At the hardware level there are also no ones and zeroes, it's some amount of charge or voltage, or the absence of it, and it doesn't even have to be that a high voltage means a 1.

Mathematics usually uses 0 to represent false and 1 to represent true

I think it's computer science that does that, not mathematics.

Some mathematicians believe that 0 and -1 should be used from the perspective of truth tables

Some operations on booleans have an equivalent in operations on integers. For example, if you use 0 for false and 1 for true, then a logical AND is equivalent to multiplication of those integer values. You can then also see that this no longer works if you use 0 for true and 1 for false.
When working with registers of a fixed width, you are working in a ring with modular arithmetic, and usually signed numbers are stored in two's complement. That means -1 is equivalent to all bits in that register being 1. This can make some things easier, for example in the following piece of C code:
bool a = …;
int x = 123;
int y = a ? x : 0;

The compiler could then replace the conditional expression with a bitwise AND operation:
int y = x & (int)a;

Which could result in much faster assembly being generated. However, since using just 1 and 0 for true and false is so common, most CPUs provide instructions to handle that as fast as storing booleans as -1 and 0 would.
Also, note that in C and languages that use the same ABI, 0 is false but when converting an int or other similar type to bool, any non-zero value is considered true. And while the ABI says that a boolean is stored or passed as a parameter, the value should be exactly 1 or 0, the compiler is allowed to do anything it wants behind the scenes as long as the observable end result is the same as what the language specification says. So it might actually store true as a non-zero value other than 1 if that is more expedient and nothing would break.

The solution adopted by the shell is 0 to represent true and other values ​​to represent false

Not exactly; the result of a command is not a boolean, it is an error code, where 0 means no error. The same goes for errno.

Mainstream FFIs all default 0 to false

Because C defined false to be zero, and most FFIs use C's ABI.

CPU initialization is all 0 initialization,

Not necessarily, and especially not the memory. A BIOS or operating system's first task is usually to zero all memory. The CPU has defined reset values for some of the registers, and some of those reset values might not be zero. When a program is started by the operating system, it's also not the case that all registers are zero.
What is true is that often the CPU provides a fast way to set a register to zero, either by having specific instructions for that or by having a special register that is always zero, and that you can copy into other registers. And even if there is nothing explicit, you can almost always XOR a register with itself.
> **Comments:**
> **username_1** (2024-05-26): Actually, many if not all C and C++ ABIs specify that `bool` values must be passed and stored as 0 or 1, nothing else. This allows functions to use bitwise operations on `bool` inputs without spending extra instructions to coerce to 0/1. Of course this is unrelated to the language semantics that nonzero values of *other* types are "truthy".  
> **username_1** (2024-05-26): Thanks to de Morgan's law, if we take 0 for true and 1 for false, we can still use bitwise logic instructions to do Boolean logic: now boolean AND corresponds to bitwise OR, and vice versa.  
> **username_17** (2024-05-26): I should rephrase that. While I know the ABI says `bool` must be passed as 0 or 1, the as-if rule applies as well; if the compiler can see how and where things are passed, it can do things differently behind the scenes, as long as the end result is the same. And when converting an `int` to a `bool` for example, any non-zero value `int` value becomes `true`.  
---
### Answer by username_5 on 2024-06-02. Score: 0
As long as the code stays "inside" the type safe language you have created it does not really make much difference. In a fully type safe language there should be no way for the program to extract the actual representation. Each and every access to the boolean should pass through the type system which should protect the internal representation. There should be no type-unsafe conversions from/to boolean to say integer. Adding an integer and a boolean should either trigger a compilation error or trigger a type conversion with exact definition. C is notoriously bad when it comes to this, it is more or less an addition to the assembler. You are allowed to do a lot of not type-safe stuff with booleans, such as AND with a bit mask on a packed boolean bit field.

In theory your language could have different representations on different hardware platforms - the later stage of compilation will generally translate into actual hardware instructions (especially if the code is interpreted). This is possible as every translation to/from boolean should be type safe. It should not be possible to do an unsafe store of an integer into a boolean as one example.

The effect of the choice you make will show itself in some other areas. There could be a performance penalty on some CPU architectures depending on your choice. My personal guess is that the difference will be minute, but the only way to know is to measure the difference on larger actual software systems.

You also have to consider what happens when the boolean leaves the "inside" of the type controlled system. This can be when calling external code as in linking in external libraries. Other examples include storing data to external files or when interpreting data read from other programs.

So, it all boils down to your choices as language designer. You need to start on how you want the type conversions to work - what happens when you assign as example a real to a boolean? Should it be allowed and when should it translate into true/false.

One additional complication is if you want to add a "not-a-boolean" value to your type, as in the "not-a-number" we have for real values.

If you want my suggestion: do as others have done. Let 0 be false and anything else be true. When translating from boolean to other types, translate true to 1.
---
### Answer by username_6 on 2024-05-29. Score: -1
Logically, it doesn't matter which two values you take as long as your logical operations are programmed appropriately. Use bathroom sinks and kitchen sinks, for instance :-).

Physically, 0 (bit pattern 0…0) and -1 (bit pattern 1…1) result in the most stable storage under two assumptions: the two's complement representation is used, and the bits are stored independently. No memory can hide from the radiation of space completely; all DRAM modules (even with ECC) sooner or later experience bitflips (inevitably, incorrectable), even on the ground.

An example of a usage of 0 and -1 is SQL in MS Access: there, TRUE is -1, and FALSE is 0.

Two asides are worth being made.

First, you might also wonder about other pairs of bit patterns with the same maximal distance, say, 01010101 and 10101010 for 8-bit words. Then you'd have to use comparison with a constant instead of testing for the majority of zeros or ones. The the simple bitcount test (“does a given byte have at least 4 ones?”) would be replaced by the more complicated counting the number of positions with a deviation from one of the two constants (“does a given byte coincide with the constant on at least 4 positions?”). So I don't advise other bit patterns (unless there are other, independent reasons).

Second, as for the faults in rotational media and in transmissions over long distances, according to my own recollection, the bits need not be stored independently, the faults in them may be correlated, and bits may be skipped/inserted, so before changing your Boolean values to anything to increase tolerance to physical faults, take a look at the actual way the data is stored or transmitted in your application.
> **Comments:**
> **username_7** (2024-05-30): Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer).  
> **username_8** (2024-05-30): I don't think a *citation* is necessary to establish that setting all 1 bits and all 0 bits makes the values maximally different in their representation, and thus "most stable".  
> **username_1** (2024-05-30): If you use 0 for false and -1 for true, then a bitflip will give you some value that equals neither.  Say a bit is flipped in a 0 value and gives you 1024.  Do you treat that as false as well?  This suggests a convention where any value with the *majority* of bits set to 1 is treated as true, but that's going to be quite expensive to implement on a typical computer, especially if you don't have a hardware popcount instruction.  Do you know of any existing language or implementation where this is actually done?  
> **username_1** (2024-05-30): Or do you treat 1024 as invalid, and insert frequent tests for such invalid values?  
> **username_1** (2024-05-30): @KarlKnechtel: Well, but you can say the same of `0xDEADBEEF` and `0x21524110`, or any other two complementary values.  So 0 and -1 are at least not *unique* in this regard  
> **username_6** (2024-05-30): @NateEldredge Clearly one needs to check whether the majority of bits is 1 or 0 and try to revive the value from that. I am unaware of programs doing this, but I've also not looked into the ***actual*** instructions in the code of the safety-critical or mission-critical programs (only experience through someone else), and these are the ones we should be looking at directly. I mean the program code running medical robots, controlling access to weapons, and stuff like that—there, the expense is justified and, depending on the purpose, a millisecond more might not matter.  
> **username_9** (2024-05-30): If error-correction from cosmic ray bitflips is required, then it needs to be provided at the hardware level, not by the programming language for just one data type. Your argument that ECC memory alone cannot protect against all corruption, doesn't imply that we should implement redundant error-correction in software; that would still not protect against all corruption, for the same reason. Either way, you have to set a probability of failure low enough that you accept it. Then it makes much more sense to just choose ECC RAM which achieves that low probability.  
> **username_6** (2024-05-30): @kaya3 ECC only lowers the rate of incorrectable bitflips and raises the chances of detecting bitflips. ECC does not fully avoid the bitflips (corrected or detected) completely, even on the ground. ECC also doesn't protect against many bits being flipped simultaneously without being detected (in my recollection, at least 3 per byte). As there is no absolute protection, if redundancy in software (in addition to proper hardware) helps and doesn't hurt too much, there's no reason not to do it. After all, the choice of ECC DRAM modules is limited, compared to the non-ECC DRAM.  
> **username_6** (2024-05-30): @kaya3 As for the other datatypes, you should, ideally, consider them too. There is no limit to perfection. Boolean values are used to guide the control flow (say, turn the engines on/off or check whether they are on/off), which is often more important than data (say, telemetry). So if any datatype should be considered to be hardened against physical faults at all at a low cost, Bool would be a good start. Frankly, I don't feel comfortable talking in general, about all code. We should start by inspecting a tiny real-world example of machine code in a safety- or mission-critical application.  
> **username_9** (2024-05-31): *"As there is no absolute protection, if redundancy in software (in addition to proper hardware) helps and doesn't hurt too much, there's no reason not to do it."* Adding better error correction in hardware is better than adding redundant error correction in software. When you are already using error correcting codes in hardware, it is not *a priori* true that the most likely error to go uncorrected by the hardware is a single bit flip ─ as such, you don't generally get the combined value of two error-correcting codes when you use them together.  
> **username_9** (2024-05-31): Also, booleans used for control flow tend to be retained in the register for a very short time (they are typically computed and then consumed by the next instruction), so there is practically no opportunity for them to become corrupted while they are stored anywhere. In short, what you're proposing in this answer is not a solution to a real problem, and if the problem were real, then this wouldn't be a good solution to it.  
> **username_6** (2024-05-31): @kaya3 No, adding hardware error correction is NOT ALWAYS better than adding software error correction. (Note that these two kinds are complementary, so comparing them is partially meaningless.) If your DRAM stores magnitudes less of control bits than of data bits with inherent inaccuracies (photos, video, or audio) or that is short lived (weather), adding hardware error correction would spend precious resources MOSTLY on stuff not worth it. Your software might even run on a not easily replaceable non-ECC memory or an apriori unknown memory type, so you might not even have a choice here.  
> **username_6** (2024-05-31): @kaya3 No, Booleans are stored not only in registers, but also in the volatile main memory. Also in the caches of long-term–storage media. (Also in the storage itself, though the bits are stored there not necessarily independently, so you'd need to look carefully into the storage implementation before taking this into account. The rotational storages have hardware error correction usually built in anyway and already heavily rely on it.) In short, what you're proposing in your comments is an invalid argument and eristic in any case.  
> **username_10** (2024-05-31): **Comments have been [moved to chat](https://chat.stackexchange.com/rooms/153426/discussion-on-answer-by-alma1r-which-number-should-be-considered-as-true-false); please do not continue the discussion here.** Before posting a comment below this one, please review the [purposes of comments](/help/privileges/comment). Comments that do not request clarification or suggest improvements usually belong as an [answer](/help/how-to-answer), on [meta], or in [chat]. Comments continuing discussion may be removed.  
---
### Answer by username_11 on 2024-06-01. Score: -2
Using a unique Boolean definition, where zero represents actual and 1 represents false, can introduce confusion and workable blunders in code interpretation, especially when participating with others or using libraries that observe the traditional definition. It may also lead to surprising behaviors and make code tougher to recognize and maintain. Therefore, deviating from the fashionable Boolean definition can cause compatibility problems and increase the threat of bugs in software program development.
> **Comments:**
> **username_7** (2024-06-02): Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer).  
---
