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.

Heroku

This site is built on Heroku

Join the ranks of developers at Salesforce, Airbase, DEV, and more who deploy their mission critical applications on Heroku. Sign up today and launch your first app!

Get Started

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

AWS Security LIVE!

Hosted by security experts, AWS Security LIVE! showcases AWS Partners tackling real-world security challenges. Join live and get your security questions answered.

Tune in to the full event

DEV is partnering to bring live events to the community. Join us or dismiss this billboard if you're not interested. ❤️