`'''$tcl_precision'''`, a [tclvars%|%built-in] Tcl variable, specifies the number of digits to generate when converting [Computers and real numbers%|%floating-point] values to strings. ** See Also ** [expr]: [IEEE binary float to string conversion]: ** Documentation ** [http://www.tcl.tk/man/tcl/TclCmd/tclvars.htm%|%official reference]: [TIP] [http://tip.tcl.tk/132%|%132]: Describes several changes to the conversion between floating-point numbers and strings, primarily to ensure that [string] equality implies value equality. New in Tcl [Changes in Tcl/Tk 8.5%|%8.5] ** Description ** As of Tcl [Changes in Tcl/Tk 8.5%|%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 when Tcl converts a number to a string, the fewest digits necessary to distinguish a floating point number 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. If `$tcl_precision` is set to a value other than `0`, scenarios that violates [EIAS] semantics can occur: ======none % set tcl_precision 12 12 % set a [expr 1.00000000000123] 1.0 % set b [expr 1.0] 1.0 % expr { $a == $b } 0 % expr { $a eq $b } 1 ====== Additionally, numbers that [shimmer] to strings and back again can lose precision: ====== expr (1/3.0) == .3333333333333333 expr {(1/3.0) == .3333333333333333} set x [expr 1/3.0] expr $x == .3333333333333333 expr {$x == .3333333333333333} ====== when `$tcl_precision` is `0`, the results are: ====== 1 1 1 1 ====== but when `$tcl_precision` is `15`, the results change to: ====== 1 1 0 1 ====== `$x` was handed unbraced to `[expr]`, which then concatenated its arguments to form an expression, and in the process used the string value of `$x`. Subsequently, `[expr]` converted that string value, which was truncated due to the `$tcl_precision` of `15`, back into a floating-point value, and in the process, some precision was lost. One more reason to [Brace your expr-essions], and not to mess with the value of `$tcl_precision`. 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] [http://www.tcl.tk/cgi-bin/tct/tip/132.html%|%#132] into Tcl [Changes in Tcl/Tk 8.5%|%8.5], Tcl behaves like this : ======none % 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: ======none % 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. <> Internals | expr