Version 2 of What kinds of numbers does Tcl recognize

Updated 2015-02-08 13:11:29 by dkf

Purpose: To discuss the various kinds of numbers that Tcl can recognize.

The obvious first place to begin on this topic is the integer. An integer is a whole name. For Tcl before version 8.5, a variable could be expected to hold a positive, negative, or zero value equal to what would be held in a C long variable.

To set a Tcl variable to an integer is pretty simple.

 % set zero 0
 0
 % set positive 12345
 12345
 % set negative -12345
 -12345
 % set octal 0123
 0123
 % expr $octal + 1
 84
 % set hex 0xfeed
 0xfeed
 % expr $hex + 1
 65262

In the older Tcl, there were some unfortunate consequences of representing the number using C data types. One consequence is this - when a variable's value grew large enough, it would eventually raise a Tcl error indicating that the value was too large to be represented as an integer. There were also cases where unexpected results might be seen:

set i 9223372030000100000               ;# see i incrementing
set j 9900000000000000000               ;# see i considered < 0
set k 99000000000000000000              ;# see i considered too large
proc count {i} {
    while { $i > 0 } {
        incr i
        if {[ expr {$i % 100000}] == 0 } {
            puts $i
        }
    }
    return $i
}
puts "final value [count $i]"
puts "final value [count $j]"
puts "final value [count $k]"

on a SPARC Solaris 9 system using Tcl 8.4.7 reported:

 9223372030000200000

:

 9900000000000000000
 integer value too large to represent
    while executing
 "incr i"
    (procedure "count" line 3)
    invoked from within
 "count $i"
    invoked from within
 "puts "final value [count $i]""
    (file "/tmp/.lwv/tstint.tcl" line 15)

Notice in the initial set commands above, there are two that result in something that the beginner might find unexpected.

Why did the expr using $octal return an 84 when the developer set it to 0123? That's because, in older Tcl's, a value with a leading zero was treated as a base 8 (also known as octal) value. [add pointer to the hazards of octal, the raging debates on how tcl should treat such values, etc.]

And what about the $hex value? That assignmend had one numeric digit - 0 and the rest alphabetic characters! The leading 0x indicates that the remainder of the string should be treated as if it were a base 16 (or hexadecimal) value.

In Tcl 8.5, a literal octal string will be able to be represented with a leading 0o and a literal binary string will be able to be represented with a leading 0b.

If a developer is reading in data from a user, a socket, a file, etc. then it is their responsibility to make use of scan or some other method to get the string converted from the appropriate base into a decimal value for Tcl.

Next there are floating point values.

 % set a 1.1
 1.1
 % expr $a + 1
 2.1
 % set a 1.0e10
 1.0e10
 % expr $a + 1
 10000000001.0

[Add comments here about the dangers of floating point, and add references to wiki pages extolling the various numerical methods for using binary floating numbers in comparisons, calculations, etc.]