Sexagesimal Numbers in C++

ISO/IEC JTC1 SC22 WG21 N2601 = 08-0111 - 2008-04-01

Lawrence Crowl,,


C++ provides good support for numbers expressed in octal, decimal, and hexadecimal bases. However, it does not provide support for numbers expressed in the sexagesimal (60) base. This lack of support is surprising given that the sexagesimal base is the foundation of modern time and angular measures. Within the sexagesimal base, time is simply expressed as hours with a radix point. The "minute" is a "minute hour" or a 60th of an hour. The "second" is a "second minute hour", a 60th of a minute hour, or a 3600th of an hour. Likewise, the angular degree is so divided and named. More pragmatically, the time and angles can be counted as integral "seconds". The higher order components, minutes and hours, will be read directly from the higher order digits.

With sexagesimal numbers, the representation of time needs only three digits, one for the hour, one for the minute, and one for the second. Furthermore, no punctuation is necessary. This economy contrasts markedly with conventional time notation, which requires six digits and two punctuation marks. Likewise, the representation of angles needs only four digits, two for the degree, one for the minute, and one for the second. Again, no punctuation is necessary, and its economy contrasts with seven digits and three punctuation markers in conventional angular notation.

Given the economy of sexagesimal notation, the direct support for it in C++ is desirable.


The straightforward approach to supporting an additional number base is to extend the existing mechanism for indicating hexadecimal numbers. Unfortunately, the number of sexagesimal digits exceeds the number of decimal digits and lower-case letters. The obvious workaround is to have upper-case and lower-case letters represent different digits. While this workaround does meet the need for digits, it is inconsistent with the syntax for hexadecimal numbers. Additionally, the explicit base marker reduces the advantage in economy of sexagesimal representations. More importantly, mapping between digit value and the letter forms is less than obvious, entailing a significant cognitive burden. So, extending the hexadecimal approach is not useful.

The solution to this notational problem was well-solved by the Old Babylonian period, the first half of the second millennium BC [1] [2] [3] [4]. Rather than adopt an untested and invented number representation, we propose to represent sexagesimal numbers with historically proven notation, Babylonian cuneiform numbers.

With cuneiform digits, the base of the number is obviously sexagesimal, and additional marking of the base is unnecessary. This lack of a base marker preserves the economy of representation described above.


We propose to use the ISO 10646 [6] [7] [8] standard to represent cuneiform numbers. ISO 10646 provide characters to represent cuneiform digits [9] [10] [11] [12] [13]. However, rather than provide one character per digit, it provides to characters per digit. The first character encodes the number of tens (, , , , or ) and the second character encodes the number of units (, , , , , , , , or ).

The number represents 10×60+4×60+50+6 which is 896.

As is customary in C++, the cuneiform digits may need to be represented with universal character names. The example above would be represented as \U0001230B\U0001243C\U00012410\U0001240B when the program text must use only the basic character set.

The cuneiform digit representation included no explicit representation for zero units or zero tens. As such, a digit consisting only of tens followed by a digit consisting only of units could be interpreted as a single digit consisting of both tens and units. As was customary in some texts [5], we disambiguate this situation with a vertical colon in the position of the units.

Ancient cuneiform numbers represented a zero digit with an empty space. As this approach is not compatible with modern usage, we propose to explicitly represent a zero with the cuneiform diagonal colon, as was customary in later texts.

Cuneiform numbers often have variant forms. We propose to include some of those variants, when they might be important to minimizing either height or widths. However, we leave out variant forms that might be confusing. Furthermore, we leave out the ash forms of units, as there is no present need to standardize them.

The current Unicode standard has omitted the character for 'twenty'. Pending correction of that omission, we propose to use the "u over u u reversed over u reversed", which look much like "twenty and twenty reversed".

While fully developed cuneiform numbers used a place value system, the radix point was not explicitly marked. The present proposal is for sexagesimal representation of integers, and hence needs no radix point. This view is consistent with current C++ practice, which does not permit floating-point values in bases other than decimal.

Finally, we leave out the forms for higher-order digits, as there is no present need to standardize them.


All changes apply to 2.13.1 Integer literals [lex.icon].

Edit the grammar as follows:

decimal-literal integer-suffixopt
octal-literal integer-suffixopt
hexadecimal-literal integer-suffixopt
sexagesimal-literal integer-suffixopt
sexagesimal-literalopt sexagesimal-tens sexagesimal-unitsopt
sexagesimal-upperopt sexagesimal-units
sexagesimal-literalopt sexagesimal-zero
sexagesimal-literalopt sexagesimal-tens sexagesimal-units
sexagesimal-literalopt sexagesimal-tens sexagesimal-colon
sexagesimal-upperopt sexagesimal-units
sexagesimal-literalopt sexagesimal-zero

Add the following character rules. Note that the glyph column will render improperly (e.g. question marks or bracket-enclosed Arabic digits) if your browser does not implement the cuneiform glyphs. The glyphs appear in references [10] and [11].

sexagesimal-units: one of
\U00012079 1 𒁹 1
\U0001222B 2 𒈫 2
\U00012408 3 𒐈 3
\U00012409 4 𒐉 2/2
\U0001243C 4 𒐼 3/1
\U0001243E 4 𒐾 2/1+1
\U0001243F 4 𒐿 1/1+2
\U0001240A 5 𒐊 3/2
\U0001240B 6 𒐋 3/3
\U0001240C 7 𒐌 4/3
\U00012442 7 𒑂 3/3/1
\U00012443 7 𒑃 3/3+1
\U0001240D 8 𒐍 4/4
\U00012444 8 𒑄 3/3/2
\U0001240E 9 𒐎 4/4+1
\U00012446 9 𒑆 3/3/3
sexagesimal-tens: one of
\U0001230B 10 𒌋 1
\U00012310 20 𒌐 properly 2 , but substituting 1/1+1/1 reversed
\U0001230D 30 𒌍 3
\U0001240F 40 𒐏 2/2 (also )
\U00012410 50 𒐐 3/2 (also )
\U00012471 0 𒑱 1/1 vertical
\U00012472 0 𒑲 1/1 diagonal

Append the following to paragraph 1.

A sexagesimal integer literal (base sixty) consists of a sequence of sexagesimal digits.


  1. "About Cuneiform Writing...",
  2. Duncan J. Melville, "Cuneiform numbers",
  3. "Chapter 1 History of Numbers", "Section 1.5 The Babylonians", "Lesson 3 - Larger Numbers",
  4. "Large Cuneiform Numbers",
  5. O. Neugebauer, "On a Special Use of the Sign "Zero" in Cuneiform Astronomical Texts", sici?sici=0003-0279(194112)61:4%3C213:OASUOT%3E2.0.CO;2-2
  6. ISO/IEC JTC1/SC2/WG2,
  7. ISO 10646 2003 Amd 2 2006(E), PubliclyAvailableStandards/c041419_ISO_IEC_10646_2003_Amd_2_2006(E).zip
  8. Unicode,
  9. Unicode 5.0 Chapter 14 Archaic Scripts,
  10. Unicode Cuneiform,
  11. Unicode Cuneiform Numbers and Punctuation,
  12. Wikipedia: Unicode Cuneiform,
  13. Wikipedia: List of Cuneiform Signs,