DEV Community

Cover image for DeepCode’s Top Findings#7: Python Use Real Floor Division
cu_0xff 🇪🇺 for DeepCode.AI

Posted on • Originally published at Medium

3 2

DeepCode’s Top Findings#7: Python Use Real Floor Division

Language: Python
Defect: DivisionRounding
Diagnose: Use // instead of / to make sure the value is rounded to an integer and not fractional. %function% expects an int as its first argument.

This example is sponsored by tensorflow / models and you can follow along by loading it into your dashboard on deepcode.ai

Screenshot

I was fascinated by this as it shows a difference between Python 2.7 and 3. The code snippet below shows the interesting parts.

...
 def take_action(self, current_node_ids, action, step_number):
...
    goal_number = step_number / self.task_params.num_steps
    ...
      if n == self.episode.goal_node_ids[goal_number][i]:
    ...

Enter fullscreen mode Exit fullscreen mode

step_number and self.task_params.num_steps are both integers. In Python 2.7, the division operator / works as a floor division. But dividing integers will always result in an integer.

Python 2.7.16 (default, Jul 13 2019, 16:01:51)
[GCC 8.3.0] on linux
> 3/4
0
> 9/10
0
Enter fullscreen mode Exit fullscreen mode

This is no longer true with Python 3.

Python 3.7.4 (default, Jul  9 2019, 00:06:43)
[GCC 6.3.0 20170516] on linux
> 3/4
0.75
> 9/10
0.9
> 4/2
2.0
Enter fullscreen mode Exit fullscreen mode

See the difference? In Python 3, the division behaves differently, so you need to be careful. A division between two integers results in a floating-point number, even if there is no remainder.
What DeepCode did under the hood was a type analysis and it inferred that goal_number is a floating-point number. It traced goal_number to its definition and found it to be a result of a division of two integers. But it is later used as the parameter for an index operator which needs to be an integer. If the program calls the index-operator with float, it results in TypeError. DeepCode learned from scanning thousands of open source repos that typically this should have been a real floor division // instead of a division /. And it happens quite frequently when porting code from Python 2.7 to Python 3.

Python 3.7.4 (default, Jul  9 2019, 00:06:43)
[GCC 6.3.0 20170516] on linux
> table = [1,2,3,4,5,6,7,8,9,10]
> a = 30
> b = 10
> table[a/b]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: list indices must be integers or slices, not float
> table[a//b]
4
Enter fullscreen mode Exit fullscreen mode

To "simulate" the Python 2.7 behavior, you can use the floor division operator //.

Python 3.7.4 (default, Jul  9 2019, 00:06:43)
[GCC 6.3.0 20170516] on linux
> 3//4
0
> 9//10
0
Enter fullscreen mode Exit fullscreen mode

Not sure if this still is of interest but in Python 2.7 // works on integers just as expected so it is safe to use.

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Dive into an ocean of knowledge with this thought-provoking post, revered deeply within the supportive DEV Community. Developers of all levels are welcome to join and enhance our collective intelligence.

Saying a simple "thank you" can brighten someone's day. Share your gratitude in the comments below!

On DEV, sharing ideas eases our path and fortifies our community connections. Found this helpful? Sending a quick thanks to the author can be profoundly valued.

Okay