Skip to content
VLSI Mentor

Tcl Part I · Module 3 · Values, Variables, and Expressions

Integer and Floating-Point Division

Every other surprise in this module announces itself with an error. This one does not. When both sides of a division are whole numbers, Tcl gives you a whole number back, discarding the remainder — so a calculation that should produce 0.7 produces 0, and a percentage that should read 70% reads 0%. Nothing fails. The script runs, the report is written, and the number is wrong. This chapter shows the two correct fixes, the one that looks right and is not, and the rounding rule for negative numbers that differs from the language most engineers learned first.

Foundation13 min readTclPart IValuesArithmeticDivision

Part I · Module 3 · Chapter 3.10 · Integer and Floating-Point Division

1. The Result

Azvya Education Pvt. Ltd.VLSI Mentor
surprise.tcl
puts [expr {10 / 4}]
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
2

Not 2.5. Not an error. Two.

2. The Rule

If both operands are whole numbers, Tcl divides as whole numbers and discards the remainder.

10 / 4 is 2 remainder 2, and the remainder is thrown away. You can see the discarded part with %:

Azvya Education Pvt. Ltd.VLSI Mentor
remainder.tcl
puts "quotient:  [expr {10 / 4}]"
puts "remainder: [expr {10 % 4}]"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
quotient:  2
remainder: 2

This is the same rule C and many other languages use. What makes it dangerous in Tcl is Chapter 3.1: values carry no types, so you cannot look at a variable and tell whether it holds a whole number. You find out from the answer.

3. The Two Correct Fixes

Make one operand a real number. One decimal point is enough:

Azvya Education Pvt. Ltd.VLSI Mentor
fix-literal.tcl
puts [expr {10.0 / 4}]
puts [expr {10 / 4.0}]
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
2.5
2.5

Convert explicitly with double(). This is what you need when the value is in a variable, where you cannot add a decimal point:

Azvya Education Pvt. Ltd.VLSI Mentor
fix-double.tcl
set a 10
set b 4

puts [expr {double($a) / $b}]
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
2.5

double() is a function in expr's language — Chapter 3.7 §8 — and it says exactly what you mean: treat this as a real number.

4. The Fix That Does Not Work

This is the first thing most people try, and it is worth seeing fail:

Azvya Education Pvt. Ltd.VLSI Mentor
too-late.tcl
puts [expr {10 / 4 * 1.0}]
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
2.0

2.0, not 2.5.

Multiplying by 1.0 converted the result after the division had already discarded the remainder. The information was gone before the conversion happened. You get a real number holding the wrong value, which is worse than an integer holding the wrong value because it looks like it was computed properly.

Convert before dividing, not after.

5. The Bug This Causes

Here it is in the shape you will actually meet:

Azvya Education Pvt. Ltd.VLSI Mentor
percentage.tcl
set passed 7
set total 10

puts "wrong: [expr {100 * ($passed / $total)}]"
puts "right: [expr {100.0 * $passed / $total}]"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
wrong: 0
right: 70.0

The first line is written the way the formula reads: a pass fraction, multiplied by 100. And 7 / 10 is 0 in whole numbers, so the whole thing is 0.

A pass rate of 0% from code that looks completely reasonable. No error, no warning.

The fix in the second line also shows the better habit: put the 100.0 at the front so the whole calculation is in real numbers from the start, rather than converting in the middle.

6. Negative Numbers Round Differently Than You Expect

Now the part that even experienced engineers get wrong, because it differs from C.

Azvya Education Pvt. Ltd.VLSI Mentor
negative.tcl
puts "-10 / 4  = [expr {-10 / 4}]"
puts "10 / -4  = [expr {10 / -4}]"
puts "-10 % 4  = [expr {-10 % 4}]"
puts "10 % -4  = [expr {10 % -4}]"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
-10 / 4  = -3
10 / -4  = -3
-10 % 4  = 2
10 % -4  = -2

-10 / 4 is -3, not -2.

Tcl rounds toward negative infinity — it takes the next whole number down, always. So -2.5 becomes -3, not -2. C truncates toward zero and would give you -2.

And the remainder follows: in Tcl, % takes the sign of the divisor, so -10 % 4 is 2 and 10 % -4 is -2.

TclC
-10 / 4-3-2
-10 % 42-2

7. Rounding on Purpose

When you do want a whole number from a real one, choose the behaviour rather than letting division decide:

Azvya Education Pvt. Ltd.VLSI Mentor
rounding.tcl
set x 2.5
set y -2.5

puts "round(2.5)  = [expr {round($x)}]"
puts "round(-2.5) = [expr {round($y)}]"
puts "int(2.9)    = [expr {int(2.9)}]"
puts "int(-2.9)   = [expr {int(-2.9)}]"
puts "floor(-2.1) = [expr {floor(-2.1)}]"
puts "ceil(2.1)   = [expr {ceil(2.1)}]"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
round(2.5)  = 3
round(-2.5) = -3
int(2.9)    = 2
int(-2.9)   = -2
floor(-2.1) = -3.0
ceil(2.1)   = 3.0
  • round() goes to the nearest, away from zero on a tie.
  • int() truncates toward zero — this is the C-style behaviour if you need it.
  • floor() and ceil() go down and up, and return real numbers.

Naming the one you want is clearer than relying on what division happens to do.

8. Common Mistakes

Dividing two variables and expecting a fraction. §5. You cannot tell from the variables whether they hold whole numbers.

Converting after the division. §4. The remainder is already gone.

Assuming C's negative rounding. §6. Tcl floors; C truncates.

Using / when you wanted %. If you want "how many left over", that is %.

Writing 100 * ($a / $b). Put the real number first: 100.0 * $a / $b.

9. Exercises

Exercise 1 — the basic surprise. Predict and then check expr {7 / 2}, expr {7.0 / 2}, expr {7 / 2.0} and expr {double(7) / 2}.

Exercise 2 — fix a percentage. This reports 0. Fix it two different ways:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
set passed 3
set total 8
puts "[expr {100 * ($passed / $total)}]%"

Exercise 3 — watch the late fix fail. Run expr {7 / 2 * 1.0} and explain the result in one sentence.

Exercise 4 — negatives. Predict all four before running:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
puts [expr {-7 / 2}]
puts [expr {7 / -2}]
puts [expr {-7 % 2}]
puts [expr {-8 / 2}]

The last one is not a trap — say why.

Exercise 5 — an average. Given set values {3 4 4} and set sum 11 and set n 3, compute the average correctly. Then compute it incorrectly, and say what a reader of the output would conclude.

Exercise 6 — choose your rounding. You need to split 17 items into groups of 5 and report how many groups are needed, including a partial one. Write it two ways: with ceil(), and using / and %. Which reads better?

10. Remember

  • Two whole numbers divide to a whole number, remainder discarded. 10 / 4 is 2.
  • No error is produced. This is the one arithmetic surprise that gives you a plausible wrong number.
  • Fix it before dividing: write 10.0, or use double($a) when the value is in a variable.
  • Converting afterwards does not work. 10 / 4 * 1.0 is 2.0.
  • Put the real number at the front of a formula: 100.0 * $a / $b.
  • Tcl rounds toward negative infinity. -10 / 4 is -3, where C gives -2.
  • % takes the sign of the divisor, so -10 % 4 is 2 — convenient for wrapping an index.
  • Choose rounding explicitly with round(), int(), floor() or ceil().

One chapter left in this module, and it brings the last four together: taking text from outside your script and turning it into a number you can rely on.

Where this fits

Part of the Tcl curriculum.