16

I'm curious as to how exactly some of the logical and arithmetic operator signs were decided? The plus and minus operators make sense, but how was decided that / was the division operator or that * was the multiplication operator?

Also how did we get && as the logical AND operator or || as the logical OR operator?

Now I know not all languages use them but their use does seem widespread to a large extent. Somebody or something must have decided on there use in computer science.

11
  • 11
    There were only so many characters available to use. And once one language used them one way it was easy for subsequent languages to use them as well.
    – Jon Custer
    Sep 26, 2023 at 16:58
  • 5
    This might be a better question for langdev.stackexchange.com
    – kouta-kun
    Sep 26, 2023 at 17:10
  • 6
    The vertical bar for ‘or’ and asterisk for multiplication are probably the most mysterious. The rest seem pretty straightforward too: the ampersand has long been an abbreviation for ‘and’, the slash has been likewise used for fractions. I think it’s also well-known that doubling the symbols for logical operators came from C needing to have separate forms because bitwise operators could not be made to short-circuit. Sep 26, 2023 at 17:18
  • 7
    Vertical bar for 'or' has precedent in Backus Naur Form, as used in the Algol 60 report. I imagine Naur just chose from what was available on his typewriter, though it seems perfect for the meaning of 'alternative'.
    – dave
    Sep 26, 2023 at 17:19
  • 4
    @kouta-kun We have accepted questions about the origin of code notations before; that a new site exists that could also accept this question is not a reason to reject it here. (Also, langdev is an insufferable Bikeshedding Central.) Sep 26, 2023 at 17:22

4 Answers 4

28

Martin Richards, the designer of BCPL (based on Algol-60 and CPL, and the predecessor for B and C), had this to say on the motivation for many such decisions:

It was not until July 1967 that a specification of a character set was published that closely resembles the ASCII character set we have today. Prior to that, computers typically had their own character sets and these were often quite limited. For instance, on the first machine on which BCPL ran, namely an IBM 7094 running CTSS, the standard code used 6-bit characters packed in 36-bit words. The characters available were essentially those used in Fortran and did not include square or curly brackets ([ ] { }), semicolon (;), double quote (") or underscore (_) and commonly used terminals such as the Model 35 Teletype only permitted letters in upper case. However, at Cambridge, CPL programs used a much richer character set since they were typically prepared using a Flexowriter which was an electric typewriter that was combined with a 7-track paper tape reader and punch. The available characters included backspace and so overprinting was possible and used to represent symbols such as ≠. System words such as while were underlined to distinguish them from ordinary identifiers. BCPL on the 7094 thus had to represent lexical tokens quite differently.

Most of the commonly-used ASCII representations of operators were codified in either B or C. Many two-character tokens seem to have been chosen based on how some terminals could print one character on top of another. For example, on many paper terminals, ê would have been represented as e-backspace-^, which on a terminal that didn’t support overstriking, would display as e^. When programming languages were transitioning to ASCII in the late ’60s, this seems to have inspired several of the two-character operators familiar to us today. So, != would look like a vertical stroke across an equals sign if they were printed on top of each other. Note that =| was already taken in B for the binary operator that became |= in C.

Algol and BCPL originally had (which some machines could represent as an underlined <, and others replaced with a text mnemonic). This became =< in B and early C, and <= in BASIC, C and languages influenced by them. Probably, C reversed all the equals operators at the same time, so that typos such x=-1 for x = -1 would no longer cause so many bugs. This happened to make the existing != operator look as though x != 0 should be a synonym for x = !0, which the syntax of B did not imply. However, perhaps because all C users knew B and != is never used in a context where anyone would ever suspect it meant if (x = !0), the designers of C saw no need to change it.

Multiplication and Exponentiation

A recent question on LangDev.SX discussed the history of *. The use of an asterisk for multiplication in printed books goes back at least to Johann Heinrich Rahn in 1659. The first programming language to use it was Fortran. Fortran’s preliminary report, in 1954, proposed using × for multiplication and ×× for exponentiation.. By 1956, * and ** had been chosen instead. MATH-MATIC (deriving from work by Grace Hopper) was being developed at the same time and also settled on * sometime between 1955 and 1957. John Backus said this was a coincidence, and that he was unaware of much previous work that came to light later. He made this choice because of the very limited 48-character set of the BCD-coded punch cards he needed to support, and even removed comparisons from DO loops because of the lack of a < character (giving rise to .LT.).

The convention of ^ for exponentiation derived from Algol’s choice of (perhaps because it represents raising the exponent). Dartmouth BASIC in 1964 originally used this symbol as well, despite being primarily based on Fortran. Some early teletypes and computers displayed character 5E as , but ASCII standardized it as ^, and BASIC was the first language to officially make exponentiation ^. This symbol was later adopted by AWK and Donald E. Knuth’s TeX. The ubiquity of TeX in mathematics is probably what led other languages used primarily by mathematicians to follow suit.

Logical Operators

The Medieval Latin abbreviation & (originally a stylized et) came to be read as and in many languages that use the Latin script. Algol used for or in the reference language itself, but the hugely influential ALGOL-60 report also was the first to use BNF grammar. Its section 1.1 introduces the syntax of BNF with:

The marks ::= and | (the latter with the meaning of or) are metalinguistic connectives.

Successor languages designed after ASCII had become dominant used | to mean or within the language itself. B in particular had no short-circuting logical or, only bitwise or, and used | to mean that. BCPL and B had the optimization that a & at the top level of a conditional expression, such as if (p & q), would short-circuit.

Algol had used the standard symbol ¬ for logical not. Since that did not make it into ASCII and B had only bitwise complement (representing false as 0 and true as ~0, or -1 in two’s-complement), B used the closest available character to ¬ in ASCII, ~.

Ken Thompson would later call the choice of ^ for exclusive-or in B “a random choice of the characters left,” and say, “if i had it to do over again (which i did) i would use the same operator for xor (^) and bit complement (~)” The “(which i did)” is a reference to how he made “the better-known operator” ^ mean both bitwise complement and exclusive-or in Golang.

The && and || operators first appeared in C. Dennis Ritchie credits Alan Snyder for them.

Rapid changes continued after the language had been named, for example the introduction of the && and || operators. In BCPL and B, the evaluation of expressions depends on context: within if and other conditional statements that compare an expression's value with zero, these languages place a special interpretation on the and (&) and or (|) operators. In ordinary contexts, they operate bitwise, but in the B statement

if (e1 & e2) ...

the compiler must evaluate e1 and if it is non-zero, evaluate e2, and if it too is non-zero, elaborate the statement dependent on the if. The requirement descends recursively on & and | operators within e1 and e2. The short-circuit semantics of the Boolean operators in such `truth-value' context seemed desirable, but the overloading of the operators was difficult to explain and use. At the suggestion of Alan Snyder, I introduced the && and || operators to make the mechanism more explicit.

Speculation

The division sign / was probably chosen to represent a fraction slash, as in 2/3. The % symbol for modulus was likely picked as the closest ASCII equivalent of ÷. Its occasional use for cents might have suggested its use for a remainder.

17
  • 1
    For the use of ^ for exponentiation and XOR, compare this question on SE Stackexchange.
    – njuffa
    Sep 27, 2023 at 6:19
  • 4
    "Note that =| was already taken for the binary operator that became =| in C". Worth pointing out that, in early C iterations, the assignment operators were all the other way around i.e. you didn't have += you had =+. They were changed later (as you alluded) to obviate syntactic ambiguities.
    – JeremyP
    Sep 27, 2023 at 8:27
  • 3
    Actually, BASIC had <= and >= and <> before B or C. BASIC also introduced the ^ operator for exponentiation and seems to have pioneered the apparently radical idea of using AND and OR to represent the AND and OR operators. I've always found it distracting how willing people have been to forget BASIC's contributions to programming history, and how correspondingly willing they are to attribute things to C (or B) that neither invented. Sep 27, 2023 at 10:37
  • 1
    "Emulating AND' is just if A then if B ... but the else's can get tricky. This is necessary in BLISS, for example, which did not possess short-circuit AND.
    – dave
    Sep 27, 2023 at 13:12
  • 2
    @RBarryYoung: Didn't Fortran use .OR. and .AND. as the logical operators well before basic?
    – Flydog57
    Sep 27, 2023 at 21:50
8

but how was decided that / was the division operator or that * was the multiplication operator?

Well, in mathematics you write fractions with a horizontal line, and simple fractions that couldn't be multiple lines already used / (and today we have unicode ½ etc.), so / is really the obvious choice.

Multiplication was already sometimes written as × (and the unicode character is still called "multiplication"), so using an asterisk * was the next best approximation in ASCII.

If * is multiplication, then ** as exponentiation is also easy, as is ^ to denoate the superscript notation for exponentiation.

Using & (literally ampersand or and-per-se-and, "and by itself") for "and" is also obvious. If you want to use & for bitwise and, then && for logical "short-circuit" and isn't that mysterious.

I don't know where | for or comes from. As far as I know the C inventors tried to stay as far away from Algol as possible.

2
  • 3
    Both & and | come from BCPL. This was a change from its predecessor CPL, largely due to the desire to limit the character set to ASCII, which was standardized about the same time BCPL was being developed. Interesting history here
    – Chris Dodd
    Sep 26, 2023 at 22:00
  • | came to C from BCPL via B. | is not a symbol in the Algol 60 reference language, though it may be used in some implementation. | is used as a delimiter in if and case clauses in Algol 68 (the brief forms).
    – dave
    Sep 26, 2023 at 22:00
4

With respect to && and ||, there are two issues at play.

Firstly, what symbols shall be used for 'and' and 'or'? Many choices have been made:

∧ ∨ (Algol 60)
.AND. .OR. (Fortran)
& | (BCPL)

It comes down to a consideration of what will be available on the expected input devices.

Secondly, what are the semantics? In 'A and B', should B be evaluated if A is known to be false? In 'A or B', should B be evaluated if A is known to be true? If you answer in the negative, it follows that 'A and B' differs from 'B and A' - the operator is no longer commutative.

One workaround is to say that the meaning is context-dependent: 'if' conditions are different to assignments (as in BCPL). But that's not nice.

The alternative is to introduce different syntax for the short-circuit cases. C in particular did this. Now the question is, what symbols to choose for the new operators?

I'd suggest that doubling-up (&&, ||) nicely conveys both that they are related to 'and' and 'or' (&, |) but different. I can't think of any better within C's self-imposed restriction to the ASCII character set.

Since then, many other languages, particularly 'brace languages', have followed suit on the grounds of familarity.

3
  • 1
    Back in the 1970s, I used to really dislike FORTRAN's relational operators since they were written in allcaps and often without spaces, but I think writing an expression as x = foo .rdiv. bar; to perform e.g. rounding integer division would be clearer than trying to understand all the other ways someone might try to write similar constructs.
    – supercat
    Sep 26, 2023 at 22:01
  • The choices made for BCPL seem to be due to character set limitations, so choosing ASCII replacements for things that use other symbols in traditional notation. This is also where ~ instead of ¬ comes from
    – Chris Dodd
    Sep 26, 2023 at 22:05
  • 3
    Re FORTRAN - not a lot of choices in the 026 character set +-0123456789ABCDEFGHIJKLMNOPQR/STUVWXYZ ='.)$*,( !
    – dave
    Sep 26, 2023 at 22:07
3

The vertical bar was in use as a kind of a binary Boolean operation since the 1910s:

In 1913, Sheffer described non-disjunction using | and showed its functional completeness. Sheffer also used ∧ for non-disjunction. Many people, beginning with Nicod in 1917, and followed by Whitehead, Russell and many others, mistakenly thought Sheffer has described non-conjunction using |, naming this the Sheffer Stroke.

While the train of thought leading to the use of | for disjunction in the B language is unclear, its established use in mathematical logic notation likely had an influence.

4
  • But the Sheffer Stroke is NAND, and not OR.
    – dirkt
    Sep 27, 2023 at 20:33
  • @dirkt That's exactly why I've said that the train of thought leading to its use for OR is unclear. Note, however, that | and which Sheffer used for NOR, are effectively the same symbols as | and ^ for OR and XOR, so "Look, here's characters which look like ASCII, being used for some Boolean functions! Let's use them for the Boolean functions that we need in our language!" does not seem too far-fetched.
    – Leo B.
    Sep 27, 2023 at 20:43
  • 1
    @LeoB.: I find it a bit curious that programming languages never seem to have a bitwise operator for "AND NOT", which would be to "OR" what "-" is to "+". It would for many purposes be semantically superior to using separate bitwise "AND" and "NOT" operators because the type of the right operand would be balanced with the left operand before negation, so 0x987654321uLL __andnot__ 0x80000000u would yield 0x907654321 even though on a 32-bit or 64-bit system 0x987654321uLL &~ 0x80000000u would yield 0x07654321uLL.
    – supercat
    Sep 27, 2023 at 21:56
  • The PDP-11 and VAX of course have 'AND NOT' instructions in their repertoire: "bit clear'. 'BIC R1,R2` means R2 := R2 & ~R1
    – dave
    Sep 27, 2023 at 23:51

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .