This is an interesting issue, since it touches on a few subtle things.
% expr int(0.57 * 10000)
5699
This code (with no substitutions, so it works “unsurprisingly”) shows that floating point numbers are surprising things in themselves. In particular, 0.57 doesn't have an exact representation as an IEEE double precision floating point number (which is base-2); in fact, it's representation is a little bit lower than exactly 0.57 and so when rounded down (which is what int(...)
does; the 10000 itself is exact) you go down to 5699. You'll see the same behavior with other languages too.
% expr int([expr 0.57 * 10000])
5700
Now this is particularly interesting. You're seeing first the inner computation being done and the resulting float converted to a string (because there's really no other way to do it). Now, you must be using Tcl 8.4 (or before) where the default number rendering rules were (in effect) what you'd get by printing the first 15 significant digits of the number; in this case that gives you 5700.00000000000
(well, with some truncation of zeroes on the right) and that's then reinterpreted from scratch as first a double (exactly 5700.0) and that's then converted to 5700.
The rules for number conversion changed in Tcl 8.5. Nowadays, when Tcl converts floating point numbers to strings, it produces the shortest string which will convert back to exactly the same floating point number (i.e., a side trip through the land of strings will give the same bit pattern in the resulting double). This means in turn that you now never see a difference between the two things above. (If you really want to force a fixed number of decimal places, use format %.15g [expr 0.57 * 10000]
.)
You also won't the observed behavior with 8.0 to 8.4 if you brace your expressions properly, as the community has advised people to do for well over a decade:
$ tclsh8.4
% expr {int([expr 0.57 * 10000])}
5699
That's because this doesn't force the result of the internal expr
call to be interpreted as a string. (It's also faster and safer.)