Rounding Up a Number in Python - python-2.7

I am trying to round up a number using math module in python.
So when I do,
print math.ceil(21/10)
I get '2.0' which is right.
print math.ceil(27/10)
I still get '2.0'
I want to get 3, since it is closest to 2.7
Could someone please advise a workaround.
Thanks in advance.

You are being surprised by the division operator in Python 2.x. With integers, it does integer division; 21/10 results in 2 and 27/10 results in 2.
Use 21.0/10 and 27.0/10 and you will get the correct answers.
In Python 3.x, division of integers will automatically promote to float if the division isn't even (there would be a remainder). You can get this behavior in Python 2.7 by using from __future__ import division.
By the way, pretty sure the integer ceiling of 21/10 should be 3.

I think you want round:
from __future__ import division
print round(27/10)
3.0
print round(21/10)
2.0
math.ceil will always round up, round will round to the nearest
You only get 2 from math.ceil(21/10) because of how python2 handles integer division.
21/10 in python2 is 2

The problem is Python thinks 27/10 are integers and so the evaluates that as 2. If you write 27/10.0 it will make them floats and the thing will work as you want.

Related

SAS Getting Simple Calculation Wrong

I can't believe I have never had this issue before (nor can I find anyone else with the same issue) but today I have just discovered that SAS sometimes gets simple calculations wrong!?! I noticed that one of my records wasn't getting picked up in the right group based on a value being <3.6 and thought there must be something strange in my data with decimal places. But on investigation I found it was just because SAS was calculating the value wrong! For some reason that I can't fathom, it seems that SAS calculates 90 - 86.4 as 3.59999999999999!!! Simple program below to show this:
code
output
If I alter the calculation to 10 - 6.4 I get the correct value of 3.6000 but for some reason this one is coming out wrong. Could there be some mad setting that is wrong in my installation? I tried both SAS EG and Base SAS and both have the same issue. I feel like I'm going mad! Any help appreciated.
Thanks.
Floating point arithmetic, in any language, will have this same issue. The same issue is possible to understand in human terms, assuming the human doesn't have a concept of infinite. If you only write down 4 digits for your decimals, for example, then:
1 - (1/3) - (1/3) - (1/3)
That's zero, right?
1 - 0.3333 = 0.6667
0.6667 - 0.3333 = 0.3334
0.3334 - 0.3333 = 0.0001
Nope! Computers do the same thing, but in binary, so they have a different (and larger) set of "problem" numbers. 1/10, for example, is not representable in binary - so adding or subtracting 0.1 is not always a "neat" operation like it is in decimal.
SAS uses 8 byte floating points, and so it gets ~15 digits of accuracy. Assuming you're not working in a field where 15 digits of accuracy is needed, you should simply round.
if round(value,.01) ge 3.6 then ... ;
Most of the time this isn't needed, but strictly speaking you should always compare rounded numbers whenever using floating point numbers (as SAS does). Integers are safe, but if you're working with 0.1 etc., use ROUND or FUZZ for integers.
Sorry Cannot replicate your findings.
data x;
a=90-86.4;
run;
Gives the correct result. Are you using any formats or put function. Share the complete code.

numpy.where returning empty index

So I'm trying to create two arrays using numpy. One array is a lot bigger than the other, so I want to search the large array to see where each element in my small array are located (i.e. what index). However when I run the code below, one of the elements in the small array cannot be found and I'm not sure why. Is it a data type mismatch?
Please advise, thank you!
import matplotlib.pyplot as plt
import numpy as np
GMean = np.array([4.23, 4.93, 5.67, 6.62, 4.67])
conc_x = np.arange(0.0, 90, 0.1)
GMean = np.round(GMean, decimals=1)
for i in np.nditer(GMean):
spec_index = np.where(conc_x==i) #look for index in conc_x data set where our GMean data point lies
print i
print spec_index
console output:
4.2
(array([42]),)
4.9
(array([49]),)
5.7
(array([57]),)
6.6
(array([], dtype=int32),) #why can it not find the index here?
4.7
(array([47]),)
So using numpy.around() instead of numpy.round() works. I get an index every time.
I thought they were the same but looking at the documentation, there is a subtle difference:
"Round an array to the given number of decimals."
vs:
"Evenly round to the given number of decimals."
So i'm thinking "evenly round" means it is rounding all trailing digits beyond the desired decimal, and therefore, both numbers you are comparing become exactly the same.
Hope this makes sense.

float precision in python

I want a floating point precision like Fortran in python program. In Fortran using pi gives a value of 3.141592653589793238462643 while using same numpy.pi gives a value of 3.141592653589793. Is it possible to get floating point accuracy like Fortran in python? Tried float128 but did not work. Any suggestion will be highly appreciated.
You can use mpmath to create floats of an arbitrary precision:
from mpmath import mp
mp.dps = 25
mypi = (mp.quad(lambda x: mp.exp(-x**2), [-mp.inf, mp.inf]) ** 2)
print mypi # 3.141592653589793238462643

Is there an implementation of range() which is not limited to integers?

The Python range() built-in function is limited to integers.
I need a more generic function of similar signature range(start, stop, step), where start, stop and step may be of any types given that:
result of (possibly multiple) addition of step to start is defined,
both start and the result mentioned above can be compared with stop.
The function may be used (for example) to obtain a sequence of days of the year:
range(datetime.datetime(2015, 1, 1),
datetime.datetime(2016, 1, 1),
datetime.timedelta(1))
I know I can easily write such function by myself. However, I am looking for efficient existing solutions in some popular package (like numpy or scipy), working with both Python 2 and Python 3.
I have already tried to combine itertools.takewhile with itertools.count, however the latter seems to be limited to numbers.
You can do this with a simple generator. The following example works with floats, integers and datetime.
With datetime you just need to clearly specify the exact date (1 Jan 2016) not just 2016 and clearly specify the time delta (timedelta(days=1) not timedelta(1))
import datetime
def range2(start,stop,step):
value = start
while value <= stop:
yield value
value += step
for date in range2(datetime.datetime(2015,1,1),datetime.datetime(2016,1,1),datetime.timedelta(days=1)):
print(date)
As for off-the-shelf solutions there is arange in numpy but I haven't tested that with datetime.
>>> from numpy import arange
>>> arange(0.5, 5, 1.5)
array([0.5, 2.0, 3.5])

summation of numbers is coming incorrect in python 2.7

In python 2.7, i am adding below numbers in the given order(since i am getting, those data from db in the same order)
24.73+1+.33+.33+.33+.33+.33+.33+.33+.33+.33+.33+.33+.33+.33+.33+.33+.33+.33+.33+.33+8
summation is coming as 39.99999999999997
but actual answer is 40
any suggestion will be helpful. thanks in advance
From the Python documentation on floats:
Note that this is in the very nature of binary floating-point: this is
not a bug in Python, and it is not a bug in your code either. You’ll
see the same kind of thing in all languages that support your
hardware’s floating-point arithmetic (although some languages may not
display the difference by default, or in all output modes).
So, this is just the way floating numbers work. To get the results you are expecting, try using the decimal module.
>>> 24.73+1+.33+.33+.33+.33+.33+.33+.33+.33+.33+.33+.33+.33+.33+.33+.33+.33+.33+.33+.33+8
39.99999999999997
>>> s = "24.73+1+.33+.33+.33+.33+.33+.33+.33+.33+.33+.33+.33+.33+.33+.33+.33+.33+.33+.33+.33+8"
>>> sum([Decimal(x) for x in s.split('+')])
Decimal('40.00')