Code: Select all
oc>gk=2.2e-9*1e11
first instance of gk
oc>gk
220
oc>print gk
220
oc>int(gk)
220
oc>strdef foo
oc>sprint(foo,"%d",gk)
1
oc>foo
219
oc>{printf("%20.15f\n", gk)}
219.999999999999972
oc>float_epsilon
1e-11
oc>float_epsilon=1e-20
oc>print gk
220
oc>int(gk)
219
No bug. Just another example of the finite precision of digital calculations. 2.2e-9 is one of the many (most, in fact) numbers whose binary representation in most floating point libraries is an infinite series. It is truncated before being multiplied by 1e11. The result stored in gk is therefore not quite equal to 220. The small difference is obscured by hoc's
print gk
which reports the "single precision" evaluation of gk (i.e. truncated with rounding at 8 significant figures), and by
int(gk)
which truncates at a level of precision controlled by the built-in constant float_epsilon.
Please read the Programmer's Reference entry on float_epsilon, which governs logical comparisons and integer truncations of floating point numbers. With the default value of float_epsilon (1e-11), int(gk) is 220, but when float_epsilon is reduced to 1e-20, int(gk) returns 219.
Note that the documentation of float_epsilon contains the caveat that not every floating comparison in NEURON uses float_epsilon, but most of them do, including all interpreter logical operations, int, array indices, and Vector logic methods. Apparently sprint() and printf() also ignore float_epsilon--which is appropriate since printf statements are often an essential tool in ferreting out the causes of simulation errors.
The bottom line: avoid writing code that invites truncation error, e.g. by multiplying a very small number by a very large number and then expecting the result to be a whole number.