skip to content

In Ruby, what do 7 / 2, -7 / 2 and 7 / 2.0 return, and how do you split 100 cents three ways?

level: juniorimportance: must knowfreq 70%

answer

  1. both Integers: Integer result
  2. floors toward negative infinity
  3. one Float operand: Float result
  4. divmod returns [quotient, modulus]
  5. Integer zero raises, Float zero gives Infinity

basics

~20 s

7 / 2 is 3 and -7 / 2 is -4, because Integer division floors; 7 / 2.0 is 3.5, because a Float operand gives Float division. Split with 100.divmod(3), which returns [33, 1], and hand out the leftover cent.

solid answer

~40 s

When both operands are Integers, `/` returns an Integer rounded toward negative infinity: `7 / 2` is `3`, and `-7 / 2` is `-4`, not `-3`. If either side is a Float, the result is a Float, so `7 / 2.0` and `7.0 / 2` are `3.5`. Dividing an Integer by exact `0` raises `ZeroDivisionError`, while `7.0 / 0` returns `Infinity`. To split a restaurant bill, keep the amount in integer cents and use `divmod`: `100.divmod(3)` returns `[33, 1]`, the floored quotient and the leftover, so two people pay 33 and one pays 34, and the shares always add back to 100. Plain `/` would silently drop the leftover cent, and converting to Float to share it invites rounding errors.

code

ruby · 14 lines
ruby
7 / 2          # => 3
-7 / 2         # => -4   (floored, not truncated)
7 / 2.0        # => 3.5
7.div(2.0)     # => 3
7.0 / 0        # => Infinity

bill = 100      # cents
diners = 3
share, extra = bill.divmod(diners)   # => [33, 1]
shares = Array.new(diners) { |i| i < extra ? share + 1 : share }
shares         # => [34, 33, 33]
shares.sum     # => 100

bill / diners  # => 33, and a cent is lost

go deeper

for a junior

Recall that two Integers give an Integer quotient, one Float operand gives a Float, and Integer division by zero raises ZeroDivisionError.

for a middle

Explain flooring toward negative infinity, why -7 / 2 is -4, and how divmod keeps quotient and modulus consistent for bucketing.

for a senior

Insist on integer minor units and divmod for money and quotas, and review any division on values that can go negative for flooring surprises.

for a principal

Standardise how the codebase represents money and splits totals, so rounding and leftover-cent rules are decided once instead of per feature.

Division is where Ruby's arithmetic operators surprise newcomers most, because the **types of the operands** decide what `/` does, and because Integer division **floors** instead of truncating. ## What / returns In Ruby, `/` is a method on the left operand: `7 / 2` is `7./(2)`, handled by `Integer#/`. Its behaviour depends on both operands: | Expression | Result | Why | |---|---|---| | `7 / 2` | `3` | Integer by Integer gives an Integer | | `-7 / 2` | `-4` | the quotient is floored toward negative infinity | | `7 / -2` | `-4` | same flooring when the divisor is negative | | `7 / 2.0` | `3.5` | a Float divisor gives Float division | | `7.0 / 2` | `3.5` | `Float#/` with an Integer argument | | `7 / 0` | `ZeroDivisionError` | Integer division by exact zero | | `7.0 / 0` | `Infinity` | Float division by zero follows IEEE 754 | Two definitions: - **Flooring** means rounding down toward negative infinity: -3.5 becomes -4. - **Truncating** means dropping the fractional part, rounding toward zero: -3.5 becomes -3. Ruby's Integer `/` floors. For positive operands the two agree, which is why the difference hides until a negative number turns up - a refund, a temperature, an offset. ## Related division methods - **`Integer#div`** always floors and returns an Integer, even with a Float argument: `7.div(2.0)` is `3`. - **`Integer#divmod`** returns `[quotient, modulus]` in one call, with the quotient floored and the modulus equal to `self % other`, so `q * divisor + r` always gives back the original number. - **`Integer#fdiv`** returns a Float quotient; it is the explicit way to ask for `3.5`. - **`Integer#**`** raises to a power; note that `2 ** -1` returns the Rational `(1/2)`, not a Float, so exponentiation can also change the result type. ## Splitting a restaurant bill Money should be held in **integer minor units** (cents), never as a Float, because binary floating point cannot represent most decimal fractions exactly. Splitting 100 cents three ways then becomes an integer problem: ```ruby total = 100 people = 3 share, leftover = total.divmod(people) # => [33, 1] shares = Array.new(people) { |i| i < leftover ? share + 1 : share } shares # => [34, 33, 33] shares.sum # => 100 ``` The steps: 1. `divmod` gives the base share (`33`) and how many cents are left over (`1`). 2. The first `leftover` people pay one extra cent each. 3. The shares always add back to the total, so no cent disappears and none is invented. Common wrong versions: - `total / people` alone gives `33` each and silently loses a cent. - `total / people.to_f` gives `33.333333333333336`, and rounding each share gives 99 in total with `round` or 102 with `ceil` - never exactly 100. - Using Floats for the running total accumulates representation error over many bills. ## Why flooring matters beyond money Flooring keeps `/` and `%` consistent: for any Integers `a` and non-zero `b`, `a == (a / b) * b + (a % b)`. With `-7` and `2`, `-7 / 2` is `-4` and `-7 % 2` is `1`, and `-4 * 2 + 1` is `-7`. That identity is what makes `divmod` safe to use for bucketing - grouping timestamps into slots, assigning tables to waiters, paginating - even when values go negative, because every value lands in exactly one bucket and the bucket index never skips. ## Reading division in code review A few patterns deserve a second look whenever you see `/` in Ruby code: 1. **Averages and percentages** computed from Integer counts: `hits / total * 100` is `0` whenever `hits < total`, because the Integer division happens first. Reorder to `hits * 100 / total` or use `fdiv`. 2. **Negative inputs** reaching Integer division, such as refunds or time offsets: the result floors, so `-1 / 2` is `-1`, not `0`. 3. **Mixed types by accident**: a value read as a Float from a config file turns an intended Integer split into a fractional one. 4. **Division by user-supplied counts**: an Integer zero raises `ZeroDivisionError`, which is usually better than the silent `Infinity` a Float gives. ## Checklist - Both operands Integer: Integer result, floored. - Any Float operand: Float result; exact-zero Float division gives `Infinity` or `NaN` instead of raising. - Need both parts: `divmod`. - Need a fractional result on purpose: `fdiv`, or make one operand a Float. - Money: integer cents plus `divmod`, never Float division.

  • In Ruby, what does 7 / 0 do compared with 7.0 / 0 and 0.0 / 0?
    `7 / 0` raises `ZeroDivisionError`, because Integer division by exact zero is an error. `7.0 / 0` returns `Infinity` and `0.0 / 0` returns `NaN`, because Float division follows IEEE 754 and produces special values instead of raising.
  • Why does Ruby's Integer division floor instead of truncate?
    Flooring keeps `/` consistent with `%`, whose result takes the divisor's sign: `a == (a / b) * b + a % b` holds for every sign combination. That makes `divmod`, bucketing and wrap-around arithmetic behave the same for negative numbers as for positive ones. Truncating division is still available through `remainder` for the modulus side.
  • In Ruby, what type does 2 ** -2 return?
    A Rational, `(1/4)`. `Integer#**` with a negative Integer exponent returns an exact Rational rather than a Float, so exponentiation can change the result type just as a Float operand does for `/`.

saying these in an interview costs you the question

  • -7 / 2 in Ruby is -3 because Integer division truncates toward zero.
  • Ruby's / always returns a Float when the division is not exact.
  • Dividing an Integer by zero in Ruby returns Infinity.
  • Store bill amounts as Floats and round each share at the end.
  • 100 / 3 * 3 gives back 100 in Ruby.