Python Arithmetic Problem

There’s this programming assignment I have in mooc where it says, “Please write a program which asks for the number of students on a course and the desired group size. The program will then print out the number of groups formed from the students on the course. If the division is not even, one of the groups may have fewer members than specified.”

My code is:
image

Originally it took me a minute to figure out adding a variable, “mot” to be equal to the math.ceil operation to fix 11/3 being rounded down to 3 instead of up to 4 like it wanted. However the test says 200/99 is not being rounded up to 3 from 2.02 and is instead rounded down to 2.

What code am I missing where any float number like 2.02 (200/99) gets rounded up to the next integer/whole number?

Since you cannot have a faction of a student i wonder if you should be using int math not float?

You might find the divmod builtin function useful Built-in Functions — Python 3.11.4 documentation

If you stick with floats research rounding of floats.

You could do

quotient, remainder = divmod(students, group)
if remainder == 0:
  return quotient
return quotient + 1

Why not just use

math.ceil(students / group)

Because using floating point for an integer problem is a domain error right?

1 Like

Extreme example, but to get an idea

>>> ceil(1/10**400)
0
>>> divmod(1,10**400)
(0, 1)

math.ceil returns an int

>>> math.ceil(200/99)
3

The 200/99 in there turns the 200 and 99 into float. For example for students = 10**18+1 and group = 10 you get that math.ceil((10**18 + 1) / 10) is telling you to use 10^{17} groups, instead of 10^{17}+1. This is because, when 10**18+1 gets turned into float, the information about the +1 gets lost.

Of course 200 / 99 is a float. That’s the point of using math.ceil, giving the correct int result. Except for 10**18+1 students. But…on what planet are you? On mine, 10**9 would amply suffice. I feel too many mathematicians here. As an engineer, I prefer the simple practical solutions :slight_smile:

I’m sure these all worked, but I did this one and it did. I made it that complicated problem of dividing by a float and multiplying by 2, because the problem 11 and 3 wasn’t giving the right answer and that fixed it. But I fixed one number problem and not them all. Just using math.ceil and integer division not float division from this code worked wonders, thank you

Sure, I have seen that ego shielding before. That “simple practical” sounds like “street smart”.

We are in a planet where specifications change all the time, and the solution that was intended for students, is now wanted for particles. Doing implicit, unintended, transformations to data is a recipe for unintended bugs.

I’m reminded of comments in RFC 2795 about uniquely numbering monkeys, and how a fixed-width integer large enough to store the number of atoms in the universe would prevent “implementations that may utilize sub-atomic monkeys and/or multiple universes”.

Sometimes it’s worth being correct, even when you think it won’t ever matter. For example, the altitude of an aircraft is always a positive number, right? You’d never have a negative altitude, or the plane’s already crashed! Except if you’re flying to the Dead Sea. Oops.

Meh, complicated. Just do floor division in the upside down.

If you’re writing a general purpose library, that makes sense. But we wouldn’t solve a lot of practical problems if we would have to be concerned about the possible use of our software on totally unrelated problems. Don’t shoot the guy who solved the initial problem. Shoot the one that applied the student software on particle theory. But anyways, thanks for the example that doesn’t work.

What is “the upside down”?

The name perhaps inspired by Stranger Things, and really just turning the world upside down so that floor and ceiling switch roles. For this purpose, achieved by negation.

-(students // -group)
1 Like

I see. I couldn’t have guessed, haven’t seen that series.

I love this description. Evocative.

There’s a little-known operator* that converts floor divisions to ceiling divisions. It’s spelled --0--. Example usage:

>>> 10//3
3
>>> --0-- 10//3
4

This leaves a problem, though: if you consistently use this operator for ceiling divisions in your code, then when a code reviewer encounters a // division without the operator, they’re left unsure whether you meant floor division, or whether you just forgot to include the ceiling division operator. Luckily, there’s a companion operator* ~-0-~ that allows you to reassure your reviewer that you really did mean floor division.

>>> ~-0-~ 10//3
3

I recommend that one of these two operators always be used when using // with integers. Explicit is better than implicit, after all.

[*] For clarity, no these aren’t actually operators. They do work, though.

3 Likes

This is not deserving of “wat”; this is actually a result of how awesome it is that unary minus and binary minus have different precedence. However, if you ever actually do this, then… wat.

1 Like