Different answers for division in Python 3

  • Context: Python 
  • Thread starter Thread starter issacnewton
  • Start date Start date
  • Tags Tags
    Division Python
Click For Summary

Discussion Overview

The discussion revolves around the differences in results obtained from division operations in Python 3, specifically comparing the outcomes of standard division and integer division when applied to the product of two integers. Participants explore the implications of using floats versus integers in calculations, particularly in the context of computing the least common multiple (LCM).

Discussion Character

  • Technical explanation
  • Conceptual clarification
  • Debate/contested
  • Mathematical reasoning

Main Points Raised

  • One participant notes that the division operation using the / operator results in a float, which can lead to a loss of precision, while the // operator maintains integer results.
  • Another participant explains that Python 3 integers can represent arbitrarily large values, unlike floats, which have limited precision.
  • A participant shares their experience with a specific implementation of the LCM calculation, highlighting an issue with precision when using float division.
  • Suggestions are made regarding the placement of the gcd function for better usability and the potential for stack overflow with recursive implementations for large numbers.
  • There is a recognition that avoiding floats in certain calculations is necessary for achieving exact results.

Areas of Agreement / Disagreement

Participants generally agree on the limitations of float precision in Python 3 and the importance of using integer division for exact results. However, there are differing opinions on the implementation details of the gcd function and its recursive nature.

Contextual Notes

Some participants mention the potential for stack overflow with recursive gcd implementations, suggesting that iterative methods may be more practical for large inputs. There is also a discussion about the implications of data types used in calculations, which may affect outcomes.

Who May Find This Useful

Readers interested in Python programming, particularly those working with numerical computations, integer arithmetic, and algorithms for calculating least common multiples and greatest common divisors.

issacnewton
Messages
1,035
Reaction score
37
Hello

Consider the following code in Python3
Code:
n = 226553150
m = 1023473145
n*m = 231871064940156750
int(n*m/5) = 46374212988031352
n*m//5 = 46374212988031350

Now since ##n*m## is divisible by ##5##, both should be give the same answer. But the first is wrong and second is correct. What is happening here ?
 
Technology news on Phys.org
Limits of precision. The internal representation of real numbers (In this case integers) in base python comes from the C language - in which language most of python was written.

There were/are internal add in libraries for python to handle so-called bignum applications. In python 3.0 this is supposed to be handled automagically.

https://www.python.org/dev/peps/pep-0237/

You declare int() by forcing the system to use int as the datatype.

So what datatype did you use for n and m? Do you know?
 
Last edited:
  • Like
Likes   Reactions: Ibix
n and m are supposed to be positive integers. And in Python, we don't do any declarations. This is part of the code to calculate least common multiple.
Code:
# Uses python3
import sys

def lcm_efficient(a, b):
    def euclidgcd(a,b):
        if b == 0:
            return a
        remainder = a%b
        return euclidgcd(b, remainder) 
    return a*b // euclidgcd(a,b)

if __name__ == '__main__':
    input = sys.stdin.read()
    a, b = map(int, input.split())
    print(lcm_efficient(a, b))

So when I have a=226553150 and b = 1023473145, I get this weird behavior in the return statement of lcm_efficient function.
Initially I had
Code:
int(a*b / euclidgcd(a,b)

And for this particular input of a and b, the LCM is off by 2. So I changed the code. I used the property of the LCM and GCD that
LCM(a, b) x GCD(a, b) = a x b, to calculate LCM.
 
@jim mcnamara is correct. n*m/5 evaluates to a float, with attendant loss of precision. To see this, try
Python:
type(n*m)   # <class 'int'>
type(n*m/5) # <class 'float'>
 
  • Like
Likes   Reactions: BvU
IssacNewton said:
n and m are supposed to be positive integers.

But the / division operator in Python 3 is a float division operator, as others have pointed out. And floats, unlike Python 3 integers, have limited precision. Python 3 integers can exactly represent arbitrarily large integers (in Python 2 this was the "long" type, the "int" type was limited to 32 or 64 bit integers, depending on your platform). So you need to decide what the requirements are for your application.

IssacNewton said:
This is part of the code to calculate least common multiple.

For this application you need exact results, so you want to avoid floats altogether, which means you cannot use the / division operator. Using the // operator, as your revised code does, should be fine for this application; this will always return an integer. If n is not evenly divisible by m, n // m will return the largest integer less than (n divided by m), which in general might not be what is wanted. But a * b will always be evenly divisible by gcd(a, b), so this isn't an issue for your case.
 
Thanks. It makes sense now. So I should just avoid floats here. Apart from integer division operator ##//##, is there anything I could have done here ?
 
IssacNewton said:
Apart from integer division operator //////, is there anything I could have done here ?

A couple of suggestions, more for long-term usability than anything else:

(1) The euclidgcd function should be defined in global scope, not inside lcm_efficient, since euclid_gcd is useful in its own right.

(2) For large numbers, euclidgcd as you've written it can overflow the stack because it recursively calls itself. It's mathematically more elegant to write it that way, but the stack overflow can create practical problems. If you're going to make heavy use of this code with large numbers, you might want to consider rewriting euclidgcd to use a while loop instead of a recursive call.
 
Thanks Peter. You are right about euclid_gcd function. For large numbers, recursion will reach maximum depth. So iterative algorithm would be better for gcd.
 

Similar threads

  • · Replies 10 ·
Replies
10
Views
4K
  • · Replies 2 ·
Replies
2
Views
2K
  • · Replies 9 ·
Replies
9
Views
3K
  • · Replies 3 ·
Replies
3
Views
2K
  • · Replies 12 ·
Replies
12
Views
2K
  • · Replies 3 ·
Replies
3
Views
2K
  • · Replies 10 ·
Replies
10
Views
2K
  • · Replies 5 ·
Replies
5
Views
5K
  • · Replies 2 ·
Replies
2
Views
2K
  • · Replies 4 ·
Replies
4
Views
3K