What is a result of Integer division a decimal? - python

I'm not sure how integer division actually works with decimal. Considering these two examples on Python 3.x:
4/0.4 = 10.0
4//0.4 = 9.0
Regular division gives 10 but the integer division of 4 by 0.4 results in 9.0.
Do you know the behavior of integer division with decimal and why the result is this way?

The CPython's implementation of floor division of a float number, as either a dividend or a divisor, lies in the float_floor_div function, which calls the float_divmod function (which implements the divmod function) for the actual calculation, which, with the following lines of code:
mod = fmod(vx, wx);
div = (vx - mod) / wx;
...
floordiv = floor(div);
tells you that the way that floor division works for a float number is to first call the fmod function to obtain the remainder of the division, subtract the remainder from the dividend vx, and then divide it by the divisor wx, before applying the floor function on the resulting quotient div.
And if you try performing the modulo operation of 4 % 0.4, expecting it to be 0 because 4 / 0.4 should be mathematically 10:
>>> 4 % 0.4
0.3999999999999998
You'll see the classic floating error inherent from the way decimal numbers are approximated by the binary system. As a result 0.4 is actually stored as something slightly greater than 0.4, which you can verify by instantiating a high-precision Decimal object with 0.4:
>>> from decimal import Decimal
>>> Decimal(0.4)
Decimal('0.40000000000000002220446049250313080847263336181640625')
which is why 4 % 0.4 has a remainder of 0.3999999999999998 instead of 0, and as a result, with the way float_divmod calculated the quotient, by first subtracting the remainder from the dividend, you get:
>>> 4 - 4 % 0.4
3.6
so naturally,
>>> (4 - 4 % 0.4) / 0.4
9.0

Related

Why is precision of decimal points different between multiplication and division of the same math statement?

# Used "==" and "is" for equality
print(48 / 10 == 48 * 0.1)
print(48 / 10 is 48 * 0.1)
print()
# Check Both Answers Individually
print(f"48 / 10 = {48 / 10}")
print(f"48 * 0.1 = {48 * 0.1}")
In the following code, I thought both expressions would equal each other, but they do not. This is what it outputs.
False
False
48 / 10 = 4.8
48 * 0.1 = 4.800000000000001
Can someone explain why there is a difference in the result, whether you are using division or multiplication?
Even though multiplying by 0.1 and dividing by 10 are mathematically equal, in a computer program they are not.
When you write 0.1 in Python, what you get is not one tenth. It's slightly more. Here's 0.1 to 40 digits of precision:
>>> "%0.40f" % 0.1
'0.1000000000000000055511151231257827021182'
The difference is due to the fact that floating point numbers use a binary representation. You cannot represent 0.1 exactly with a finite number of binary digits, just like you can't represent 1/3 = 0.333333... exactly with a finite number of decimal digits.
Since 0.1 is slightly more than one tenth, you should expect 48*0.1 to be slightly more than 4.8. And it is:
>>> "%0.40f" % (48*0.1)
'4.8000000000000007105427357601001858711243'
You shouldn't expect 4.8 to equal 4.8 either. It's in fact slightly less than 4.8:
>>> "%0.40f" % (4.8)
'4.7999999999999998223643160599749535322189'

What is the difference between these bits of code [duplicate]

Is there a benefit to using one over the other? In Python 2, they both seem to return the same results:
>>> 6/3
2
>>> 6//3
2
In Python 3.x, 5 / 2 will return 2.5 and 5 // 2 will return 2. The former is floating point division, and the latter is floor division, sometimes also called integer division.
In Python 2.2 or later in the 2.x line, there is no difference for integers unless you perform a from __future__ import division, which causes Python 2.x to adopt the 3.x behavior.
Regardless of the future import, 5.0 // 2 will return 2.0 since that's the floor division result of the operation.
You can find a detailed description at PEP 238: Changing the Division Operator.
Python 2.x Clarification:
To clarify for the Python 2.x line, / is neither floor division nor true division.
/ is floor division when both args are int, but is true division when either of the args are float.
// implements "floor division", regardless of your type. So
1.0/2.0 will give 0.5, but both 1/2, 1//2 and 1.0//2.0 will give 0.
See PEP 238: Changing the Division Operator for details.
/ → Floating point division
// → Floor division
Let’s see some examples in both Python 2.7 and in Python 3.5.
Python 2.7.10 vs. Python 3.5
print (2/3) ----> 0 Python 2.7
print (2/3) ----> 0.6666666666666666 Python 3.5
Python 2.7.10 vs. Python 3.5
print (4/2) ----> 2 Python 2.7
print (4/2) ----> 2.0 Python 3.5
Now if you want to have (in Python 2.7) the same output as in Python 3.5, you can do the following:
Python 2.7.10
from __future__ import division
print (2/3) ----> 0.6666666666666666 # Python 2.7
print (4/2) ----> 2.0 # Python 2.7
Whereas there isn't any difference between floor division in both Python 2.7 and in Python 3.5.
138.93//3 ---> 46.0 # Python 2.7
138.93//3 ---> 46.0 # Python 3.5
4//3 ---> 1 # Python 2.7
4//3 ---> 1 # Python 3.5
As everyone has already answered, // is floor division.
Why this is important is that // is unambiguously floor division, in all Python versions from 2.2, including Python 3.x versions.
The behavior of / can change depending on:
Active __future__ import or not (module-local)
Python command line option, either -Q old or -Q new
>>> print 5.0 / 2
2.5
>>> print 5.0 // 2
2.0
Python 2.7 and other upcoming versions of Python:
Division (/)
Divides left hand operand by right hand operand
Example: 4 / 2 = 2
Floor division (//)
The division of operands where the result is the quotient in which the digits after the decimal point are removed. But if one of the operands is negative, the result is floored, i.e., rounded away from zero (towards negative infinity):
Examples: 9//2 = 4 and 9.0//2.0 = 4.0, -11//3 = -4, -11.0//3 = -4.0
Both / division and // floor division operator are operating in similar fashion.
The double slash, //, is floor division:
>>> 7//3
2
// is floor division. It will always give you the integer floor of the result. The other is 'regular' division.
The previous answers are good. I want to add another point. Up to some values both of them result in the same quotient. After that floor division operator (//) works fine but not division (/) operator:
>>> int(755349677599789174 / 2) # Wrong answer
377674838799894592
>>> 755349677599789174 // 2 # Correct answer
377674838799894587
The answer of the equation is rounded to the next smaller integer or float with .0 as decimal point.
>>>print 5//2
2
>>> print 5.0//2
2.0
>>>print 5//2.0
2.0
>>>print 5.0//2.0
2.0
Python 3.x Clarification
Just to complement some previous answers.
It is important to remark that:
a // b
Is floor division. As in:
math.floor(a/b)
Is not int division. As in:
int(a/b)
Is not round to 0 float division. As in:
round(a/b,0)
As a consequence, the way of behaving is different when it comes to positives an negatives numbers as in the following example:
1 // 2 is 0, as in:
math.floor(1/2)
-1 // 2 is -1, as in:
math.floor(-1/2)
Python 3
Operation
Result
Notes
x / y
quotient of x and y
x // y
floored quotient of x and y
(1)
Notes:
Also referred to as integer division. The resultant value is a whole integer, though the result’s type is not necessarily int. The result is always rounded towards minus infinity: 1//2 is 0, (-1)//2 is -1, 1//(-2) is -1, and (-1)//(-2) is 0.
Python 2
Operation
Result
Notes
x / y
quotient of x and y
(1)
x // y
(floored) quotient of x and y
(4)(5)
Notes:
1. For (plain or long) integer division, the result is an integer. The result is always rounded towards minus infinity: 1/2 is 0, (-1)/2 is -1, 1/(-2) is -1, and (-1)/(-2) is 0. Note that the result is a long integer if either operand is a long integer, regardless of the numeric value.
4. Deprecated since version 2.3: The floor division operator, the modulo operator, and the divmod() function are no longer defined for complex numbers. Instead, convert to a floating point number using the abs() function if appropriate.
5. Also referred to as integer division. The resultant value is a whole integer, though the result’s type is not necessarily int.
Summary
x//y : EXACT integer division
int(x/y) OR math.floor(x/y): INEXACT integer division (but almost correct)
x/y: floating point division (that has the loss of significance)
Remarkable Calculation Result
import math
N = 1004291331219602346 # huge number
print(N//100) #=> 10042913312196023 is correct answer
print(math.floor(N/100)) #=> 10042913312196024 is wrong answer
print(math.ceil(N/100)) #=> 10042913312196024 is wrong answer
print(int(N/100)) #=> 10042913312196024 is wrong answer
Consideration
I think about the evaluation of int(x/y).
At first, Python evaluate the expression x/y and get INEXACT floating number z.
Second, Python evaluate the expression int(z).
We get a wrong result when the loss of significance cannot be ignored.
// is floor division. It will always give you the floor value of the result.
And the other one, /, is the floating-point division.
In the following is the difference between / and //;
I have run these arithmetic operations in Python 3.7.2.
>>> print (11 / 3)
3.6666666666666665
>>> print (11 // 3)
3
>>> print (11.3 / 3)
3.7666666666666667
>>> print (11.3 // 3)
3.0
5.0//2 results in 2.0, and not 2, because the return type of the return value from // operator follows Python coercion (type casting) rules.
Python promotes conversion of lower data type (integer) to higher data type (float) to avoid data loss.

round down to 2 decimal in python

I need to round down and it should be two decimal places.
Tried the following,
a = 28.266
print round(a, 2)
28.27
But the expected value is 28.26 only.
Seems like you need the floor:
import math
math.floor(a * 100)/100.0
# 28.26
It seems you want truncation, not rounding.
A simple way would be to combine floor division // and regular division /:
>>> a = 28.266
>>> a // 0.01 / 100
28.26
Instead of the regular division you could also multiply (as noted in the comments by cmc):
>>> a // 0.01 * 0.01
28.26
Similarly you could create a function to round down to other more/less decimals. But because floats are inexact numbers, this can lead to inaccuracies.
def round_down(value, decimals):
factor = 1 / (10 ** decimals)
return (value // factor) * factor
print(round_down(28.266, 2))
# 28.26
But as said it's not exactly exact:
for i in range(0, 8):
print(i, round_down(12.33333, i))
0 12.0
1 12.3
2 12.33
3 12.333
4 12.333300000000001 # weird, but almost correct
5 12.33332 # wrong
6 12.33333
7 12.33333
There are other (more precise) approaches though:
A solution using the fraction module
A fraction can represent a decimal number much more exact than a float. Then one can use the "multiply, then floor, then divide" approach mentioned by Psidom but with significantly higher precision:
import fractions
import math
a = 28.266
def round_down(value, decimals):
factor = 10 ** decimals
f = fractions.Fraction(value)
return fractions.Fraction(math.floor(f * factor), factor)
print(round_down(28.266, 2))
# 1413/50 <- that's 28.26
And using the test I did with the floats:
for i in range(0, 8):
print(i, round_down(12.33333, i))
0 12
1 123/10
2 1233/100
3 12333/1000
4 123333/10000
5 1233333/100000
6 1233333/100000
7 1233333/100000
However creating a Fraction will not magically fix an inexact float, so typically one should create the Fraction from a string or a "numerator-denominator pair" instead of from float.
A solution using the decimal module
You could also use the decimal module, which offers a variety of rounding modes, including rounding down.
For this demonstration I'm using a context manager to avoid changing the decimal rounding mode globally:
import decimal
def round_down(value, decimals):
with decimal.localcontext() as ctx:
d = decimal.Decimal(value)
ctx.rounding = decimal.ROUND_DOWN
return round(d, decimals)
print(round_down(28.266, 2)) # 28.26
Which gives more sensible results for the rounding:
for i in range(0, 8):
print(i, round_down(12.33333, i))
0 12
1 12.3
2 12.33
3 12.333
4 12.3333
5 12.33333
6 12.333330
7 12.3333300
As with Fraction a Decimal should be created from a string to avoid the intermediate inexact float. But different from Fraction the Decimal have limited precision, so for values with lots of significant figures it will also become inexact.
However "rounding down" is just one of the available options. The list of available rounding modes is extensive:
Rounding modes
decimal.ROUND_CEILING Round towards Infinity.
decimal.ROUND_DOWN Round towards zero.
decimal.ROUND_FLOOR Round towards -Infinity.
decimal.ROUND_HALF_DOWN Round to nearest with ties going towards zero.
decimal.ROUND_HALF_EVEN Round to nearest with ties going to nearest even integer.
decimal.ROUND_HALF_UP Round to nearest with ties going away from zero.
decimal.ROUND_UP Round away from zero.
decimal.ROUND_05UP Round away from zero if last digit after rounding towards zero would have been 0 or 5; otherwise round towards zero.
With Python 3 you can use quantize()
from decimal import *
>>> Decimal('7.325').quantize(Decimal('.01'), rounding=ROUND_DOWN)
Decimal('7.32')
here's a simple function that isn't affected by float precision errors
def truncate_float(n, places):
return int(n * (10 ** places)) / 10 ** places
Tests:
>>> truncate_float(28.266, 3)
28.266
>>> truncate_float(28.266, 2)
28.26
>>> truncate_float(28.266, 1)
28.2
simply try this:
import math
a = 28.266
print((math.floor(a * 100)) / 100.0)
Output:
28.26
There's an even simpler way of doing this generically, by subtracting a small quantity before rounding, like so:
a = 28.269
digits = 2
print(round(a - 0.5/10**digits, digits))
This is based on the intuition that one way of rounding a float to the nearest integer is by adding 0.5, then truncating. The above solution does the opposite by subtracting a half of the minimal 'tick' that the desired precision allows, then rounding.
Simple function which you can use in your codes. This function you can also use for integer floor numbers.
import math
def floorDecimal(number, decimal):
return math.floor(number * pow(10, decimal))/pow(10, decimal)
Example of using:
number = 256.789
newNumber = floorDecimal(number, 2) # newNumber is 256.78
newNumber = floorDecimal(number, -2) # newNumber is 200
Here is the function I use with f for the float and d for the number of decimals
from math import floor
def floor_decimal(f, d):
n = 10 ** d
return floor(f * n) / n

Round to two decimal places only if repeating python

I was wondering if anybody knew of a quick way in python to check and see if a fraction gives a repeating decimal.
I have a small function that takes in two numbers and divides them. If the quotient is a repeating decimal I would like to round to 2 decimal places and if the quotient is not repeating I would like to round to just one
Example:
800/600 = 1.33333333333333 which would equal 1.33
900/600 = 1.5 would stay as 1.5
I know that I need to use the two statements for the two types of rounding
output = "{:.2f}".format(float(num))
output = "{:,}".format(float(num))
but I am having trouble with the if statement to direct to one or the other.
Can anybody help with some insight?
Use the fractions module, which implements exact rational arithmetic:
import fractions
# fractions.Fraction instances are automatically put in lowest terms.
ratio = fractions.Fraction(numerator, denominator)
You can then inspect the denominator of the result:
def is_repeating(fraction):
denom = fraction.denominator
while not (denom % 2):
denom //= 2
while not (denom % 5):
denom //= 5
return denom != 1
Just a workaround using regex :)
import re
result = str(800/600)
# result = str(900/600)
repeating_pair = re.escape(result.split('.')[1][:2])
check_within = result.split('.')[1][2:]
if re.match(repeating_pair, check_within):
print("{:.2f}".format(float(result)))
else:
print("{:.1f}".format(float(result)))
Output:
1.33
And for 900/600
1.5
Try this: Just use brute force. Since you want only 2 decimal places. Just divide and then test it when it is rounded to 0 and 1 decimal place and see where it stops being unique. If it is not unique at this point, then round to 2 decimal places.
def f(x):
if x == round(x,0):
return '{:.0f}'.format(x)
elif x == round(x,1):
return '{:.1f}'.format(x)
else:
return round(x,2)
y = [1, 2, 3, 3/2, 1/9, 8/9, 1/11, 12/11, 10/11, 14/13, 1/3]
for item in y:
print(f(item))
Output:
1
2
3
1.5
0.11
0.89
0.09
1.09
0.91
1.08
0.33
>>>
repeating decimal
There are only 10 fractions that can be written as some repeated digit - .(0), .(1), ... .(9). Thus, if you only care about repeating pattern starting right after decimal point, you only need to check against those cases.
All those numbers (and only them) give an integer if multiplied by 9.
Thus, if (9 * numenator) % denominator == 0, you'll print 2 digits.
You'll probably want to exclude .(0) pattern though. To do that, test if your fraction is in fact an integer - numenator % denominator == 0.
Also check out fractions module in case you have some wheels to reinvent.
Of course, if you only have your number as a float, there is some ambiguity about what numenator and denominator are, because floats don't actually store rational numbers like 1/3. You can experiment with fractions's .limit_denominator() to choose something that works for your case.

trouble with some python coding to estimate pi [duplicate]

Is there a benefit to using one over the other? In Python 2, they both seem to return the same results:
>>> 6/3
2
>>> 6//3
2
In Python 3.x, 5 / 2 will return 2.5 and 5 // 2 will return 2. The former is floating point division, and the latter is floor division, sometimes also called integer division.
In Python 2.2 or later in the 2.x line, there is no difference for integers unless you perform a from __future__ import division, which causes Python 2.x to adopt the 3.x behavior.
Regardless of the future import, 5.0 // 2 will return 2.0 since that's the floor division result of the operation.
You can find a detailed description at PEP 238: Changing the Division Operator.
Python 2.x Clarification:
To clarify for the Python 2.x line, / is neither floor division nor true division.
/ is floor division when both args are int, but is true division when either of the args are float.
// implements "floor division", regardless of your type. So
1.0/2.0 will give 0.5, but both 1/2, 1//2 and 1.0//2.0 will give 0.
See PEP 238: Changing the Division Operator for details.
/ → Floating point division
// → Floor division
Let’s see some examples in both Python 2.7 and in Python 3.5.
Python 2.7.10 vs. Python 3.5
print (2/3) ----> 0 Python 2.7
print (2/3) ----> 0.6666666666666666 Python 3.5
Python 2.7.10 vs. Python 3.5
print (4/2) ----> 2 Python 2.7
print (4/2) ----> 2.0 Python 3.5
Now if you want to have (in Python 2.7) the same output as in Python 3.5, you can do the following:
Python 2.7.10
from __future__ import division
print (2/3) ----> 0.6666666666666666 # Python 2.7
print (4/2) ----> 2.0 # Python 2.7
Whereas there isn't any difference between floor division in both Python 2.7 and in Python 3.5.
138.93//3 ---> 46.0 # Python 2.7
138.93//3 ---> 46.0 # Python 3.5
4//3 ---> 1 # Python 2.7
4//3 ---> 1 # Python 3.5
As everyone has already answered, // is floor division.
Why this is important is that // is unambiguously floor division, in all Python versions from 2.2, including Python 3.x versions.
The behavior of / can change depending on:
Active __future__ import or not (module-local)
Python command line option, either -Q old or -Q new
>>> print 5.0 / 2
2.5
>>> print 5.0 // 2
2.0
Python 2.7 and other upcoming versions of Python:
Division (/)
Divides left hand operand by right hand operand
Example: 4 / 2 = 2
Floor division (//)
The division of operands where the result is the quotient in which the digits after the decimal point are removed. But if one of the operands is negative, the result is floored, i.e., rounded away from zero (towards negative infinity):
Examples: 9//2 = 4 and 9.0//2.0 = 4.0, -11//3 = -4, -11.0//3 = -4.0
Both / division and // floor division operator are operating in similar fashion.
The double slash, //, is floor division:
>>> 7//3
2
// is floor division. It will always give you the integer floor of the result. The other is 'regular' division.
The previous answers are good. I want to add another point. Up to some values both of them result in the same quotient. After that floor division operator (//) works fine but not division (/) operator:
>>> int(755349677599789174 / 2) # Wrong answer
377674838799894592
>>> 755349677599789174 // 2 # Correct answer
377674838799894587
The answer of the equation is rounded to the next smaller integer or float with .0 as decimal point.
>>>print 5//2
2
>>> print 5.0//2
2.0
>>>print 5//2.0
2.0
>>>print 5.0//2.0
2.0
Python 3.x Clarification
Just to complement some previous answers.
It is important to remark that:
a // b
Is floor division. As in:
math.floor(a/b)
Is not int division. As in:
int(a/b)
Is not round to 0 float division. As in:
round(a/b,0)
As a consequence, the way of behaving is different when it comes to positives an negatives numbers as in the following example:
1 // 2 is 0, as in:
math.floor(1/2)
-1 // 2 is -1, as in:
math.floor(-1/2)
Python 3
Operation
Result
Notes
x / y
quotient of x and y
x // y
floored quotient of x and y
(1)
Notes:
Also referred to as integer division. The resultant value is a whole integer, though the result’s type is not necessarily int. The result is always rounded towards minus infinity: 1//2 is 0, (-1)//2 is -1, 1//(-2) is -1, and (-1)//(-2) is 0.
Python 2
Operation
Result
Notes
x / y
quotient of x and y
(1)
x // y
(floored) quotient of x and y
(4)(5)
Notes:
1. For (plain or long) integer division, the result is an integer. The result is always rounded towards minus infinity: 1/2 is 0, (-1)/2 is -1, 1/(-2) is -1, and (-1)/(-2) is 0. Note that the result is a long integer if either operand is a long integer, regardless of the numeric value.
4. Deprecated since version 2.3: The floor division operator, the modulo operator, and the divmod() function are no longer defined for complex numbers. Instead, convert to a floating point number using the abs() function if appropriate.
5. Also referred to as integer division. The resultant value is a whole integer, though the result’s type is not necessarily int.
Summary
x//y : EXACT integer division
int(x/y) OR math.floor(x/y): INEXACT integer division (but almost correct)
x/y: floating point division (that has the loss of significance)
Remarkable Calculation Result
import math
N = 1004291331219602346 # huge number
print(N//100) #=> 10042913312196023 is correct answer
print(math.floor(N/100)) #=> 10042913312196024 is wrong answer
print(math.ceil(N/100)) #=> 10042913312196024 is wrong answer
print(int(N/100)) #=> 10042913312196024 is wrong answer
Consideration
I think about the evaluation of int(x/y).
At first, Python evaluate the expression x/y and get INEXACT floating number z.
Second, Python evaluate the expression int(z).
We get a wrong result when the loss of significance cannot be ignored.
// is floor division. It will always give you the floor value of the result.
And the other one, /, is the floating-point division.
In the following is the difference between / and //;
I have run these arithmetic operations in Python 3.7.2.
>>> print (11 / 3)
3.6666666666666665
>>> print (11 // 3)
3
>>> print (11.3 / 3)
3.7666666666666667
>>> print (11.3 // 3)
3.0
5.0//2 results in 2.0, and not 2, because the return type of the return value from // operator follows Python coercion (type casting) rules.
Python promotes conversion of lower data type (integer) to higher data type (float) to avoid data loss.

Categories

Resources