In Python I would like to divide two numbers and if the answer is not an integer I want the number to be rounded up to the number above.
For example 100/30 not to give 33.3 but to give 4.
Can anyone suggest how to do this? Thanks.
You can use the math.ceil() function:
>>> import math
>>> math.ceil(100/33)
4
you can use the ceil function in math library that python has, but also you can take a look why in a logical sense
a = int(100/3) # this will round down to 3
b = 100/3 # b = 33.333333333333336, a and b are not equal
so we can generalize into the following
def ceil(a, b):
if (b == 0):
raise Exception("Division By Zero Error!!") # throw an division by zero error
if int(a/b) != a/b:
return int(a/b) + 1
return int(a/b)
Related
In my program I use numpy to get number's exponents, then I use the sum function to summarize them.
I've noticed that summarizing those large numbers, with or without numpy, results in the largest parameter being returned, unchanged.
exp_joint_probabilities=[ 1.57171938e+81, 1.60451506e+56, 1.00000000e+00]
exp_joint_probabilities.sum()
=> 1.571719381352921e+81
The same with just python:
(1.57171938e+81+1.60451506e+56+1.00000000e+00)==1.57171938e+81
=>True
Is this a problem with approximation? Should I use a larger datatype to represent the numbers?
How can I get a more accurate result for these kind of calculations?
You could use the decimal standard library:
from decimal import Decimal
a = Decimal(1.57171938e+81)
b = Decimal(1.60451506e+56)
d = a + b
print(d)
print(d > a and d > b)
Output:
1.571719379999999945626903708E+81
True
You could convert it back to a float afterwards, but this will cause the same problem as before.
f = float(d)
print(f)
print(f > a and f > b)
Output:
1.57171938e+81
False
Note that if you store Decimals in your numpy arrays, you will lose fast vectorized operations, as numpy does not recognize Decimal objects. Though it does work:
import numpy as np
a = np.array([1.57171938e+81, 1.60451506e+56, 1.00000000e+00])
d = np.vectorize(Decimal)(a) # convert values to Decimal
print(d.sum())
print(d.sum() > d[0]
Output:
1.571719379999999945626903708E+81
True
1.57171938e+81 is a number with 81 digits, of which you only enter the first 9. 1.60451506e+56 is a much much much smaller number, with only 56 digits.
What kind of answer are you expecting? The first utterly dwarfs the second. If you want something of a similar precision to your original numbers (and that's what you get using floats), then the answer is simply correct.
You could use ints:
>>> a = int(1.57171938e+81)
>>> b = int(1.60451506e+56)
>>> a
571719379999999945626903548020224083024251666384876684446269499489505292916359168L
>>> b
160451506000000001855754747064077065047170486040598151168L
>>> a+b
1571719379999999945626903708471730083024253522139623748523334546659991333514510336L
But how useful that is is up to you.
It does seem to be a problem with approximation:
>>> 1.57171938e+81 + 1.60451506e+65 > 1.57171938e+81
<<< True
>>> 1.57171938e+81 + 1.60451506e+64 > 1.57171938e+81
<<< False
You can get arount this by casting to int:
>>> int(1.57171938e+81) + int(1.60451506e+64) > int(1.57171938e+81)
<<< True
Could someone help check why the result is always one and let me know what I did wrong? Thanks
Correct result should be: 1/1 + 1/2 + 1/3 == 1.83333333333.
x = int(input("Enter n: "))
assert x > 0, "n must be greater than zero!"
def one_over_n(x):
result = 0
for n in range(x):
n += 1
result += 1 / n
return result
r = one_over_n(x)
print("one_over_n( {0:d} ): {1:f}" .format(x, r))
It will work correctly on python 3, but not in python 2
>>> 1/2
0
That means you are just adding zeroes, to one. You will need to change either numerator or denominator to a float number e.g. 1/2.0, so change your code to
result += 1.0 / n
See Pep 238 to see why it was changed in python 3.
btw floating point numbers can't represent all fractions, so if you are just adding fractions, you can use Fraction class e.g.
>>> from fractions import Fraction as F
>>> F(1,1) + F(1,2) + F(1,3)
Fraction(11, 6)
As an alternative, to force Python 2 perform division as you expect (rather than integer division), add:
from __future__ import division
I am new to Python and am trying to create a program for a project- firstly, I need to generate a point between the numbers 0-1.0, including 0 and 1.0 ([0, 1.0]). I searched the python library for functions (https://docs.python.org/2/library/random.html) and I found this function:
random.random()
This will return the next random floating point number in the range [0.0, 1.0). This is a problem, since it does not include 1. Although the chances of actually generating a 1 are very slim anyway, it is still important because this is a scientific program that will be used in a larger data collection.
I also found this function:
rand.randint
This will return an integer, which is also a problem.
I researched on the website and previously asked questions and found that this function:
random.uniform(a, b)
will only return a number that is greater than or equal to a and less than b.
Does anyone know how to create a random function on python that will include [0, 1.0]?
Please correct me if I was mistaken on any of this information. Thank you.
*The random numbers represent the x value of a three dimensional point on a sphere.
Could you make do with something like this?
random.randint(0, 1000) / 1000.0
Or more formally:
precision = 3
randomNumber = random.randint(0, 10 ** precision) / float(10 ** precision)
Consider the following function built on top of random.uniform. I believe that the re-sampling approach should cause all numbers in the desired interval to appear with equal probability, because the probability of returning candidate > b is 0, and originally all numbers should be equally likely.
import sys
import random
def myRandom(a, b):
candidate = uniform.random(a, b + sys.float_info.epsilon)
while candidate > b:
candidate = uniform.random(a, b + sys.float_info.epsilon)
return candidate
As gnibbler mentioned below, for the general case, it may make more sense to change both the calls to the following. Note that this will only work correctly if b > 0.
candidate = uniform.random(a, b*1.000001)
Try this:
import random
random.uniform(0.0, 1.0)
Which will, according to the documentation [Python 3.x]:
Return a random floating point number N such that a <= N <= b for a <= b and b <= N <= a for b < a.
Notice that the above paragraph states that b is in fact included in the range of possible values returned by the function. However, beware of the second part (emphasis mine):
The end-point value b may or may not be included in the range depending on floating-point rounding in the equation a + (b-a) * random().
For floating point numbers you can use numpy's machine limits for floats class to get the smallest possible value for 64bit or 32bit floating point numbers. In theory, you should be able to add this value to b in random.uniform(a, b) making 1 inclusive in your generator:
import numpy
import random
def randomDoublePrecision():
floatinfo = numpy.finfo(float)
epsilon = floatinfo.eps
a = random.uniform(0, 1 + eps)
return a
This assumes that you are using full precision floating point numbers for your number generator. For more info read this Wikipedia article.
Would it be just:
list_rnd=[random.random() for i in range(_number_of_numbers_you_want)]
list_rnd=[item/max(list_rnd) for item in list_rnd]
Generate a list of random numbers and divide it by its max value. The resulting list still flows uniform distribution.
I've had the same problem, this should help you.
a: upper limit,
b: lower limit, and
digit: digit after comma
def konv_des (bin,a,b,l,digit):
des=int(bin,2)
return round(a+(des*(b-a)/((2**l)-1)),digit)
def rand_bin(p):
key1 = ""
for i in range(p):
temp = str(random.randint(0, 1))
key1 += temp
return(key1)
def rand_chrom(a,b,digit):
l = 1
eq=False
while eq==False:
l += 1
eq=2**(l-1) < (b-a)*(10**digit) and (b-a)*(10**digit) <= (2**l)-1
return konv_des(rand_bin(l),a,b,l,digit)
#run
rand_chrom(0,1,4)
Is there a standard library function which will set a minimum value to a division operation, for example:
min(1, a/b)
This will ensure that min value of operation above will always be 1, never 0.
Such as:
min(1, 1/5)
1
Also, how do I round up a division:
round_up(1/5) = 1
I always get "0" when I divide 1/5, even with ceil function:
math.ceil(1/5)
0
If you want to use floating point division as default, you can do from __future__ import division:
>>> 1/5
0
>>> from __future__ import division
>>> 1/5
0.2
>>> math.ceil(1/5)
1.0
If you need the result to be of integer type, e.g. for indexing, you can use
int(math.ceil(1/5))
The result of 1/5 is an integer already. If you want the floating point version you need to do 1.0/5. The math.ceil function will then work as you expect: math.ceil(1.0/5) = 1.0.
If you're working with variables instead of constants, use the float(x) function to convert an integer into a floating point.
In [4]: 1/5
Out[4]: 0
In [5]: math.ceil(1/5)
Out[5]: 0.0
In [7]: float(1)/5
Out[7]: 0.2
In [8]: math.ceil(float(1)/5)
Out[8]: 1.0
You could make a round up function for integers like this
>>> def round_up(p, q):
... d, r = divmod(p, q)
... if r != 0:
... d += 1
... return d
...
>>> round_up(1, 5)
1
>>> round_up(0, 5)
0
>>> round_up(5, 5)
1
>>> round_up(6, 5)
2
>>>
Your example doesn't work because an integer dividing an integer is an integer.
As for your min question - what you wrote is probably the best you can do.
I don't know about anything in the standard library, but if you are just trying to make sure the answer is never less than 1, the function is pretty easy:
def min_dev(x,y):
ans = x/y
if ans < 1: # ensures answer cannot be 0
return 1
else: # answers greater than 1 are returned normally
return ans
If, instead, you are looking to round up every answer:
def round_up(x,y):
ans = x//y # // is the floor division operator
if x % y == 1: # tests for remainder (returns 0 for no, 1 for yes)
ans += 1 # same as ans = ans + 1
return ans
else:
return ans
This will round up any answer with a remainder.
I believe Python 3.3 (and I know 3.4) return a float by default for integer division: https://docs.python.org/3/tutorial/introduction.html
def isinteger(x):
while x > 0.0:
x = x - 1.0
if x < 0.0:
return 0.0
elif x == 0:
return 1.0
d = input('')
print isinteger(d)
The code is somewhat self explanatory. I'm using it for a fractran interpreter. Here is my problem: I input a fraction, such as 22/7, and I get a 1 as my output. Does it have something to do with python's IO?
The input function evaluates your 22/7 exactly the same way as if it had been entered into the python interpreter. Since both 22 and 7 are integers you get an integer division with a result of 3. If you want float division, enter either 22.0/7 or 22/7.0 both of which result in 3.146....
If you're using python 2, inputting "22/7" directly leads to integer division, i.e. it rounds your input down to 3, thus the algorithm returns 1. Try inputting 22.0/7 instead.
Also, you might want to consider faster alternatives to this algorithm if you're using it for anything real. Possibilities:
def isinteger(x):
return int(x) == x
def isinteger(x):
return isinstance(x, int)
22.0/7 vs 22/7 aside, there is another problem with this approach: it does not work in the majority of programming languages, because of the way floating point numbers are represented. For example, using your original function:
In [37]: isinteger(190.000000000000000001)
Out[37]: 1.0
Using Sean's int(x) == x suggestion:
In [39]: x = 190.000000000000000001
In [40]: int(x) == x
Out[40]: True
I realize it doesn't directly address the question, but I hope it will prevent a future one :)
If you want to check for integer for example for finding big perfect squares, you must consider inaccuracy of binary representations (abs is not needed for positive numbers, but is needed for negative numbers):
x = -190.00000000001
print int(x) == x
epsilon = 1E-10
def isinteger(n):
" near enoungh to pass as integer considering round of errors "
return abs(n-int(n)) < epsilon
print isinteger(x)
Implied eval of Python2 is considered too powerfull to be safe. If you want to input numbers instead of let user to give any formula (and in every case you need to add try...except handling for the users input):
number = raw_input('Give number: ')
number = int(number) if all(c.isdigit() for c in number) else float(number)
print number
your inputs are both integers so it results in giving 3 as input thereby it produces 1 as output.