Version 20 of tcl_precision

Updated 2014-05-14 16:40:03 by pooryorick

$tcl_precision, a built-in Tcl variable, specifies the number of digits to generate when converting floating-point values to strings.

See Also

expr
IEEE binary float to string conversion

Documentation

official reference
TIP 132
New in Tcl 8.5

Description

As of Tcl 8.5, changing $tcl_precision to a value other than its default value of 0 is deprecated.

The default value for $tcl_precision is 0, meaning that Tcl should convert numbers using as few digits as possible while still distinguishing any floating point numbers from its nearest neighbours. The advantage of this behaviour is that the string representation of an inexact number like 1.4 is 1.4 rather than 1.3999999999999999, allowing Tcl to maintain its EIAS semantics, and providing a more intuitive representation for script authors.

Historically, the default value of $tcl_precision was 12.

17 digits, the maximum allowed value, is "perfect" for IEEE floating-point in that it allows double-precision values to be converted to strings and back to binary with no loss of information. However, using 17 digits prevents any rounding, which produces longer, less intuitive results. For example, expr 1.4 returns 1.3999999999999999 with $tcl_precision set to 17, vs. 1.4 if $tcl_precision is 12.

All interpreters in a process share a single $tcl_precision: changing it in one interpreter will affect all other interpreters as well. However, safe interpreters are not allowed to modify it.

Since the incorporation TIP #132 into Tcl 8.5, Tcl behaves like this :

% set tcl_precision 17
17
% expr 1.4
1.4

This change doesn't affect the inherent limitations to the precision of binary floating point numbers:

double(1.4)

is still less than the Platonic real number, 7/5. This can be proven by multiplying it by three:

% expr {3 * 1.4}
4.199999999999999

Interestingly enough, multiplying by 5 yields an exact result:

% expr {5 * 1.4}
7.0

sbron: KBK mentioned in the Tcl Chatroom that after TIP #132 a value can be displayed the same way as before by using format with a formatstring of %#.12g

KBK 2014-05-14 in the Tcl Chatroom: The work put into Tcl's floating-point conversion - making float->string->float bit-for-bit lossless - wasn't so much for precision or performance as it was to continue to satisfy EIAS.


Donald Porter's wise advice, in comp.lang.tcl, slightly edited:

It is best to use $tcl_precision in a global way. Set it early in your program's execution, then leave it alone. For situations like above where you want to control precision of single assignment, use format.

Historically, if you were doing any math at all where you care about getting the right answer, you would just set ::tcl_precision 17, and then forget anyone suggested anything else. The current recommendation is not to change ::tcl_precision at al.


RS: The funny thing about $tcl_precision is that it's not there in the beginning - it is just created on demand (trace?):

% info vars
tcl_rcFileName tcl_version argv argv0 tcl_interactive auto_oldpath auto_path err
orCode errorInfo auto_index env tcl_patchLevel argc tcl_libPath tcl_platform tcl
_library
% set tcl_precision
12
% info vars
tcl_rcFileName tcl_version argv argv0 tcl_interactive auto_oldpath auto_path err
orCode tcl_precision errorInfo auto_index env tcl_patchLevel argc tcl_libPath tc
l_platform tcl_library
% unset tcl_precision
% set tcl_precision
12

Now you see it - now you don't. $tcl_precision is the only variable I know that can be read after being unset.

DGP: You don't know about $tcl_interactive then? Common trait - they are Tcl_LinkVar variables, script level representations of C values.