# Introducing Tcl 8.7 Part 7: numbers

Published

This is the seventh in a series of posts about new features in the upcoming version 8.7 of Tcl. This post deals with some additional facilities, albeit minor, in handling of numbers.

To take Tcl 8.7 for a spin, you can download the source distribution. Binary distributions for Windows are available from magicsplat and BAWT.

## Introduction of `0d` as a decimal radix prefix

Tcl 8.6 recognized the use of `0b`, `0o` and `0x` (and upper case variants) as binary, octal and hexadecimal radix prefixes respectively. These were recognized in numeric literals, `expr` and `format` commands etc. Tcl 8.7 adds recognition of `0d` as a decimal radix prefix.

This makes Tcl's support for radix prefixes consistent. In addition, it simplifies treatment of decimal numbers from an external source such as a CSV file. For example, consider the fragment below that prints the increments an input number:

``````% set val [gets stdin] ; expr {\$val * 2}
0123
166``````

Most people would be surprised by the result which is a consequence of Tcl treating `0123` as a octal number. Fixing this in Tcl 8.6 requires the use of `scan` to ensure the input is treated as decimal.

``````% set val [gets stdin]
0123
0123
% scan \$val %d val
1
% puts [expr {2*\$val}]
246``````

In Tcl 8.7, we can force interpretation of the input as decimal a little more simply with the `0d` prefix.

``````% set val 0d[gets stdin] ; expr {\$val * 2}
0123
246``````

No, not a earth-shattering feature but nice to have the consistency and Tclers have a fetish for consistency!

## Classifying floating point numbers

The other addition related to numerics is ability to classify floating point numbers. Personally, I have never found a need for these but then again I have zero experience with serious numerical computation which is where I imagine these would be handy.

I assume the reader knows what the terms normal, subnormal, finite, infinite mean. If not, it's unlikely you will need to use these :-)

TIP 521 defines one new command, `fpclassify` and six additional functions to in the `::tcl::mathfunc` namespace.

The `fpclassify` command returns a value that indicates the class to which a floating point number belongs. This class may be one of `zero`, `normal`, `infinite`, `subnormal` and `nan`.

The first four are easy enough to demonstrate.

``````% fpclassify 0
zero
% fpclassify 1.0
normal
% fpclassify [expr {1.0/0.0}]
infinite
% fpclassify 5e-324
subnormal``````

The `nan` classification cannot currently be generated at the script level via a mathematical computation because an expression such as `expr 0.0/0.0` generates an error (by design). TIP 520 proposes changing this to return a `NaN` instead but that TIP is still pending for acceptance into 8.7. Nevertheless, `NaN` can still occur in values, those passed from external C libraries for example. For demonstration purposes, we resort to some bit twiddling.

``````% binary scan [binary decode hex 7ff0000000000001] Q dbl_nan
1
% set dbl_nan
NaN(1)
% fpclassify \$dbl_nan
nan``````

Related to this classification, Tcl 8.7 adds five functions to the `::tcl::mathfunc` namespace - `isfinite`, `isinf`, `isnan`, `isnormal`, `issubnormal` - that return booleans that reflect whether the passed value falls into that category.

``````% expr {isnan(\$dbl_nan)}
1
% expr {isfinite(1.0/0.0)}
0
% expr {isinf(1.0/0.0)}
1``````

One additional function, `isunordered` takes two values and returns a true boolean value if the two values cannot be compared. In particular, consider comparison with `Inf` or `NaN`.

``````% expr {isunordered(Inf,0)}
0
% expr {isunordered(\$dbl_nan,0)}
1
% expr {isunordered(\$dbl_nan,\$dbl_nan)}
1``````

Note the last example where `NaN` is not comparable to even itself.