Version 10 of Why does Tcl think a fraction less than one is zero?

Updated 2011-05-06 15:16:05 by GeoffM

The short answer is that Tcl (like most comuter languages) doesn't do fractions; it only knows about integers and floating-point numbers. Hence expr doesn't "evaluate" fractions, but the way you would ask it to compute a quotient may look like as it evaluates a fraction.

[Explain idioms of "computer arithmetic".]

Sometimes, Tcl's expression handling can be a little bit unexpected to newcomers:

 % expr 1/2
 0

This is because the above code asks for integer division (this is true in many other languages too) and that (conceptually) contains a round-down-to-int of the result. (The remainder operation, %, is often useful when you're working with integer division).

 % puts "1/2 is [expr 1/2] remainder [expr 1%2]"
 1/2 is 0 remainder 1

If you really want to end up with a half, force one of the arguments to the division operation to be a floating-point value:

 % expr double(1)/2
 0.5

See expr problems with int for more on integer division and how to avoid it.


rdt : 2005-01-27 : This is a property of integers that can take on values of 0,1,2,... and therefore have no values between 0 and 1. However:

 % expr 1.0 / 2
 0.5

show the expected value. Whereas in a calculator, most math is done in floating point, in Tcl, floating point math is only performed when you explicitly say to do so.


GWM A quaint gotcha to beware of:

expr 225/119/84. => 0.0119047619048

while

expr 225./119/84 => 0.0225090036014

In the the first case the division (225/119) is performed as integer division (giving 1) then divided by the real 84. In the second case 225./119 is floating point and divided by 84 gives the correct answer.

You can use wide to give more precision to your integers (if 64 bits is supported on your platform) however:

expr wide(225.)/119/84. => 0.0119047619048

since the real number is cast to a long integer by wide, then integer divided as before.


Occasionally integer multiplication is hit by precision problems:

(bin) 13 % expr 12345000*100

1234500000

(bin) 14 % expr 12345000*1000

-539901888 (!!!)

(bin) 15 % expr 12345000*100000

1844386048 (!!!++)

But wide saves the day...

(bin) 16 % expr wide(12345000)*100000 1234500000000 (bin) 17 % expr 12345000*wide(100000) 1234500000000

for a bit (!!--):

(bin) 19 % expr 12345000*wide(100000)*wide(100000)*wide(100000) 4128214688309968896


Category Mathematics