Division by Zero Errors - python

I have a problem with this question from my professor. Here is the question:
Write the definition of a function typing_speed , that receives two parameters. The first is the number of words that a person has typed (an int greater than or equal to zero) in a particular time interval. The second is the length of the time interval in seconds (an int greater than zero). The function returns the typing speed of that person in words per minute (a float ).
Here is my code:
def typing_speed(num_words,time_interval):
if(num_words >= 0 and time_interval > 0):
factor = float(60 / time_interval)
print factor
return float(num_words/(factor))
I know that the "factor" is getting assigned 0 because its not being rounded properly or something. I dont know how to handle these decimals properly. Float isnt doing anything apparently.
Any help is appreciated, thankyou.

When you call float on the division result, it's after the fact the division was treated as an integer division (note: this is Python 2, I assume). It doesn't help, what does help is initially specify the division as a floating-point division, for example by saying 60.0 (the float version of 60):
factor = 60.0 / time_interval
Another way would be divide 60 by float(time_interval)
Note this sample interaction:
In [7]: x = 31
In [8]: 60 / x
Out[8]: 1
In [9]: 60.0 / x
Out[9]: 1.935483870967742

Sharth meant to say: from __future__ import python
Example:
>>> from __future__ import division
>>> 4/3
1.3333333333333333
>>>

Related

How do I increase the amount of decimal points?

This code is used to estimate pi, with the highest objective being time efficiency. With this in mind, I need to increase the amount of decimal places, as currently it is bottlenecked down to 2.
import numpy as np
def main(max_iterations=200):
a, b= np.random.random(max_iterations), np.random.random(max_iterations)
return 4 * (a ** 2 + b ** 2 < 1).sum() / max_iterations
main()
Example of current output:
3.13
One thing I noticed was that upon adding 0s to the max_iterations parameter, the number of decimal places increased along with it. Though, I need a solution within the function, where it wouldn't matter what the value of the parameter was.
Example of what I want as an output:
3.127722772277228
Don't divide an integer by a number with trailing zeros if you want more significance.
With max_iterations=200:
%Run pi_test.py
3.08
With max_iterations=201:
%Run pi_test.py
3.084577114427861

Divide values in Python

I made a xlrd to json parsing script, which doesn't divide variables. It always returns zero... the code which I am using to divide the variables is:
if not row_values[2]:
key['nr_one'] = 0
else:
key['nr_one'] = int(row_values[2])
if not row_values[4]:
key['nr_two'] = 0
else:
key['nr_two'] = int(row_values[4])
try:
key['perc'] = float(key['nr_two']/key['nr_one']*100)
except ZeroDivisionError:
key['perc'] = 0
I have printed the following code at the end of the script:
print('one')
print(key['nr_one'])
print('two')
print(key['nr_two'])
print('perc')
print(key['perc'])
This returns:
one
103386547
two
135680054
perc
0.0
So. I don't understand why the division fails and returns 0? Could someone please help me format a good way to calculate the percentage
it should be float(key['nr_two']) /key['nr_one']*100
Integer division is like this :
1/3 #=> 0
The easiest way to understand this result is not as a fraction, but as the answer to the question "How many times do 3 fit in 1?".
So 0 multiplied by 100 is still :
1/3 * 100 #=> 0
You need
100.0*1/3 #=> 33.333333
For your code :
key['perc'] = 100.0*key['nr_two']/key['nr_one'] (without using float(...))
It returns :
76.1987808465937
NOTE: You really need to type 100.0 (a float), not just 100 (an int). You'd get 76 otherwise.
key['nr_two'] is integer and so is key['nr_one']. So when they are divided, the result is forced to be an integer in Python 2x versions (in Python 3x this limitation does not exist and your code would run just fine). What you therefore get, is 0, which is later multiplied by 100, so still 0 but float, 0.0.
To achieve float division in python 2.x you can just add:
from __future__ import division
This way you will not need to convert your numbers each time you divide them.

Round python decimal to nearest 0.05

I'm trying to round money numbers in Decimal to the nearest 0.05. Right now, I'm doing this:
def round_down(amount):
amount *= 100
amount = (amount - amount % 5) / Decimal(100)
return Decimal(amount)
def round_up(amount):
amount = int(math.ceil(float(100 * amount) / 5)) * 5 / Decimal(100)
return Decimal(amount)
Is there any way I can do this more elegantly without dealing with floats using python Decimals (using quantize perhaps)?
With floats, simply use round(x * 2, 1) / 2. This doesn't give control over the rounding direction, though.
Using Decimal.quantize you also get complete control over the type and direction of rounding (Python 3.5.1):
>>> from decimal import Decimal, ROUND_UP
>>> x = Decimal("3.426")
>>> (x * 2).quantize(Decimal('.1'), rounding=ROUND_UP) / 2
Decimal('3.45')
>>> x = Decimal("3.456")
>>> (x * 2).quantize(Decimal('.1'), rounding=ROUND_UP) / 2
Decimal('3.5')
A more generic solution for any rounding base.
from decimal import ROUND_DOWN
def round_decimal(decimal_number, base=1, rounding=ROUND_DOWN):
"""
Round decimal number to the nearest base
:param decimal_number: decimal number to round to the nearest base
:type decimal_number: Decimal
:param base: rounding base, e.g. 5, Decimal('0.05')
:type base: int or Decimal
:param rounding: Decimal rounding type
:rtype: Decimal
"""
return base * (decimal_number / base).quantize(1, rounding=rounding)
Examples:
>>> from decimal import Decimal, ROUND_UP
>>> round_decimal(Decimal('123.34'), base=5)
Decimal('120')
>>> round_decimal(Decimal('123.34'), base=6, rounding=ROUND_UP)
Decimal('126')
>>> round_decimal(Decimal('123.34'), base=Decimal('0.05'))
Decimal('123.30')
>>> round_decimal(Decimal('123.34'), base=Decimal('0.5'), rounding=ROUND_UP)
Decimal('123.5')
First note this problem (unexpected rounding down) only sometimes occurs when the digit immediately inferior (to the left of) the digit you're rounding to has a 5.
i.e.
>>> round(1.0005,3)
1.0
>>> round(2.0005,3)
2.001
>>> round(3.0005,3)
3.001
>>> round(4.0005,3)
4.0
>>> round(1.005,2)
1.0
>>> round(5.005,2)
5.0
>>> round(6.005,2)
6.0
>>> round(7.005,2)
7.0
>>> round(3.005,2)
3.0
>>> round(8.005,2)
8.01
But there's an easy solution, I've found that seems to always work, and which doesn't rely upon the import of additional libraries. The solution is to add a 1e-X where X is the length of the number string you're trying to use round on plus 1.
>>> round(0.075,2)
0.07
>>> round(0.075+10**(-2*6),2)
0.08
Aha! So based on this we can make a handy wrapper function, which is standalone and does not need additional import calls...
def roundTraditional(val,digits):
return round(val+10**(-len(str(val))-1))
Basically this adds a value guaranteed to be smaller than the least given digit of the string you're trying to use round on. By adding that small quantity it preserve's round's behavior in most cases, while now ensuring if the digit inferior to the one being rounded to is 5 it rounds up, and if it is 4 it rounds down.
The approach of using 10**(-len(val)-1) was deliberate, as it the largest small number you can add to force the shift, while also ensuring that the value you add never changes the rounding even if the decimal . is missing. I could use just 10**(-len(val)) with a condiditional if (val>1) to subtract 1 more... but it's simpler to just always subtract the 1 as that won't change much the applicable range of decimal numbers this workaround can properly handle. This approach will fail if your values reaches the limits of the type, this will fail, but for nearly the entire range of valid decimal values it should work.
You can also use the decimal library to accomplish this, but the wrapper I propose is simpler and may be preferred in some cases.
Edit: Thanks Blckknght for pointing out that the 5 fringe case occurs only for certain values here.

Division error in python, result is incorrectly rounded [duplicate]

This question already has answers here:
How can I force division to be floating point? Division keeps rounding down to 0?
(11 answers)
Closed 8 years ago.
I am trying to make a BMI calculator function. I am learning python at pyschools.
This is my code:
# Note: Return a string of 1 decimal place.
def BMI(weight, height):
x = weight /(height*height)
g = round(x,1)
return g
And pyschools shows me that these are the right answers:
With 110 = weight and 2 = height I am supposed to get a BMI of 27,5.
But I instead get 27.
Then it does a second check to make sure I wrote the code right and tells me 24,2 is the right answer but my program did return 24,2. But it still marks my answer in red and says "my" 24,2 is wrong and the website's is right.
If someone has a better site or anything to learn python it would also be appreciated since this website seems to be kind of wrong sometimes. And I am looking for free online resources. No books please.
To fix it for all cases, add this line to the top:
from __future__ import division # Make division work like in Python 3.
in Python 2, / means integer division.
With this in mind, in Python 2 if you pass intgers into division, it will give you an integer back. Anything that would have been a float is floored*. Therefore another option to get the desired result is to pass a float in, so instead of:
weight / (height*height)
do:
float(weight) / (height*height) # float in means float out.
*This means that only full times that the divisor goes in are counted. So 1/2 will get 0 because 2 goes fully into 1 0 times.
def BMI(weight, height):
x = float(weight) /(height*height)
g = round(x,1)
return g
see Python division
and Binary arithmetic operations
The issue lies with your division.
Division as we intrinsically know it is floating point division, or division where 1 / 2 evaluates to a fraction, 0.5. In standard programatic division, the 1, 2 are ints() and therefore cant be fractions, or floats() as the type is called in python. The expression, 1 / 2 therefore evaluates as 0, as 2 as a whole integer cant go into one entirely any times.
Ex:
In [1]: 1 / 2
Out[1]: 0
# Explicitly what is going on, since 1 and 2 are ints.
In [2]: int(1) / int(2)
Out[2]: 0
#fixed with floating division
In [3]: float(1) / float(2)
Out[3]: 0.5
# protip: only one of the divisors needs to be a float for python to divide correctly.
In [4]: 1 / float(2)
Out[4]: 0.5
Use x = weight / float((height*height)) to get the results you expect.
# Note: Return a string of 1 decimal place.
def BMI(weight, height):
x = weight / float((height*height))
g = round(x,1)
return g

how to round to higher 10's place in python

I have a bunch of floats and I want to round them up to the next highest multiple of 10.
For example:
10.2 should be 20
10.0 should be 10
16.7 should be 20
94.9 should be 100
I only need it to go from the range 0-100. I tried math.ceil() but that only rounds up to the nearest integer.
Thanks in advance.
from math import ceil
def ceil_to_tens(x):
return int(ceil(x / 10.0)) * 10
Edit: okay, now that I have an undeserved "Nice answer" badge for this answer, I think owe the community with a proper solution using the decimal module that does not suffer from these problems :) Thanks to Jeff for pointing this out. So, a solution using decimal works as follows:
from decimal import Decimal, ROUND_UP
def ceil_to_tens_decimal(x):
return (Decimal(x) / 10).quantize(1, rounding=ROUND_UP) * 10
Of course the above code requires x to be an integer, a string or a Decimal object - floats won't work as that would defeat the whole purpose of using the decimal module.
It's a pity that Decimal.quantize does not work properly with numbers larger than 1, it would have saved the division-multiplication trick.
>>> x = 16.7
>>> int( 10 * math.ceil(x/10.0))
The answers here are fraught with peril. For example 11*1.1 - 2.1 = 10.0, right? But wait:
>>> x = 11*1.1 - 2.1
>>> int(ceil(x / 10.0)) * 10
20
>>> x
10.000000000000002
>>>
You could try this
int(ceil(round(x, 12) / 10.0)) * 10
But choosing the number of decimal places to round to is really difficult as it is hard to predict how floating point noise accumulates. If it is really important to get this right all of the time, then you need to use fixed point arithmetic or Decimal.
If you're looking for another solution that doesn't involve float division, here's one that uses the modulus:
def ceil_to_tens_mod(x):
tmp = int(ceil(x))
mod10 = tmp % 10
return tmp - mod10 + (10 if mod10 else 0)
There's probably some way to simplify it, but there you go.

Categories

Resources