How to compute a limit of a ratio between two number? - python

I need to compute a ratio of two number that are computed in a cycle.
The problem is that b becomes too big and it is equal to numpy.inf at some point.
However, the ratio a/b should exist and not be zero.
for i in range(num_iter):
a += x[i]
b += y[i]
return a/b
What are tricks to compute this type of limits?
Please let me know if it is a wrong stackexchange site for the question.
Update:
The loop is finite, I have two arrays x and y that can be analysed in advance on big number or something.
I guess dividing x and y by some large number (rescaling) might work?

You don't say what you are adding to a and b each time through the loop, but presumably both values get so large that any error introduced by truncating the increments to integers will be negligible in the limit. This way, you use arbitrary integers rather than floating-point values, which have both an upper bound on their magnitude and limited precision.
for i in range(num_iter):
a += int(...)
b += int(...)
return a/b

Building on Chepner's idea, how about tracking the float and the int part separately, then bringing the int part back when it it is larger than 1. Something like this:
for i in range(num_iter):
afloat += ... - int(...)
bfloat += ... - int(...)
a += int(...) + int(afloat)
b += int(...) + int(bfloat)
afloat += int(afloat)
bfloat += int(bfloat)
return a/b

If a and b have the same length, you know that the ratio of the means is equal to the ratio of the sum. If it isn't, you can use the ratio of the number of items to correct you ratio.
for i in xrange(num_iter):
numpy.append(a, ...)
numpy.append(b, ...)
return (mean(a)/mean(b)) * (float(len(b))/len(a))
It could be slow and it will use more memory, but I think it should work.
If you don't want to save everything, you can calculate the mean for every N elements, and do a weighted mean when you need to calculate it.

Related

Subtraction in place of Division: How to approximate division with subtraction

I want to do division but with subtraction. I also don't necessarily want the exact answer.
No floating point numbers too (preferably)
How can this be achieved?
Thanks in advance:)
Also the process should almost be as fast as normal division.
to approximate x divided by y you can subtract y from x until the result is smaller or equal to 0 and then the result of the division would be the number of times you subtracted y from x. However this doesn't work with negatives numbers.
Well, let's say you have your numerator and your denominator. The division basically consists in estimating how many denominator you have in your numerator.
So a simple loop should do:
def divide_by_sub(numerator, denominator):
# Init
result = 0
remains = numerator
# Substract as much as possible
while remains >= denominator:
remains -= denominator
result += 1
# Here we have the "floor" part of the result
return result
This will give you the "floor" part of your result. Please consider adding some guardrails to handle "denominator is zero", "numerator is negative", etc.
My best guess, if you want go further, would be to then add an argument to the function for the precision you want like precision and then multiply remains by it (for instance 10 or 100), and reloop on it. It's doable recursively:
def divide_by_sub(numerator, denominator, precision):
# Init
result = 0
remains = numerator
# Substract as much as possible
while remains >= denominator:
remains -= denominator
result += 1
# Here we have the "floor" part of the result. We proceed to more digits
if precision > 1:
remains = remains * precision
float_result = divide_by_sub(remains, denominator, 1)
result += float_result/precision
return result
Giving you, for instance for divide_by_sub(7,3,1000) the following:
2.333

How to Recursively Multiply two positive integers without using the * operator (or / operator) ? . You can use addition, subtraction, and bit shifting

I stumbled upon this solution, but I am not able to understand what exactly is happening in this. Can someone please explain!
From what I understand it is trying to count the number of cells in a*b grid by counting half the cells and then doubling it. But I am not able to understand the recursive calls.
Pleas don't suggest other solutions, try to explain this solution please :)
def minProduct(a,b):
bigger = b if a < b else a #a < b ? b : a
smaller = a if a < b else b #a < b ? a : b
return minProductHelper(smaller,bigger)
def minProductHelper(smaller, bigger):
if smaller == 0:
return 0
elif smaller == 1:
return bigger
# Compute half. If uneven, compute other half. If even, double it
s = smaller >> 1 # divide by 2
side1 = minProduct(s,bigger)
side2 = side1
if smaller % 2 == 1:
side2 = minProductHelper(smaller - s, bigger)
return side1 + side2
print(minProduct(5,6))
This is a recursive divide-and-conquer algorithm, in a sense. Bit shifting left by 1 effectively divides a number by 2 (discarding any remainder). minProductHelper divides smaller by 2 using s = smaller >> 1 and then returns the recursively derived sum of s * bigger and (smaller - s) * bigger. Because of the properties of addition and multiplication, you have that ((smaller - s) * bigger) + (s * bigger) == smaller * bigger which is the outcome you want. You have two base cases which are when smaller is either 0 or 1, so you can imagine that a call to minProduct(a,b) will keep cutting a or b into halves (and those halves into halves, etc.) until all it has to do is sum a bunch of products involving 0 and some number or 1 and some number, which can be determined without having to use the * operator. The smaller number is always cut in half rather than the larger number because this allows the base cases to be reached with less recursive calls.
Suppose you are multiplying 5 and 6 together. Then the program first figures out the smallest number i.e. 5. It then calls itself by dividing the smallest number into two whole parts (nearly equal).
minProduct(5,6)=minProduct(2,6)+minProduct(3,6). Then minProduct(2,6) is calculated similarly into minProduct(1,6)+minProduct(1,6). Now that the smaller number is one the program simply returns 6 and the values are calculated back.This happens to each function call.
minProduct(5,6) =minProduct(2,6)+minProduct(3,6) =minProduct(1,6)+minProduct(1,6)+minProduct(3,6) (Let minProduct(3,6)=18) for cohesion) =6+6+18 =30
Why figure out the smallest number first?
The previous answer deals with precisely why the smaller number was used instead of the larger number. Take two arbitrary numbers 2 and 1000. I need to figure out what 2*1000 is. It is easier to figure out 1000+1000 then (2+2+. ..+2). Less function calls means faster algorithm.
Why was there a condition for minProduct(0,a)?
You did see why there was a condition for minProduct(1,a). But there was a condition for minProduct(0,a) because there is a special case for multiplication by 2. When you call minProduct(2,3). This resolves to minProduct(2,3) and minProduct(0,3). So you need to handle this separately.

Generating evenly distributed bits, using approximation

I'm trying to generate 0 or 1 with 50/50 chance of any using random.uniform instead of random.getrandbits.
Here's what I have
0 if random.uniform(0, 1e-323) == 0.0 else 1
But if I run this long enough, the average is ~70% to generate 1. As seem here:
sum(0 if random.uniform(0, 1e-323) == 0.0
else 1
for _ in xrange(1000)) / 1000.0 # --> 0.737
If I change it to 1e-324 it will always be 0. And if I change it to 1e-322, the average will be ~%90.
I made a dirty program that will try to find the sweet spot between 1e-322 and 1e-324, by dividing and multiplying it several times:
v = 1e-323
n_runs = 100000
target = n_runs/2
result = 0
while True:
result = sum(0 if random.uniform(0, v) == 0.0 else 1 for _ in xrange(n_runs))
if result > target:
v /= 1.5
elif result < target:
v *= 1.5 / 1.4
else:
break
print v
This end ups with 4.94065645841e-324
But it still will be wrong if I ran it enough times.
Is there I way to find this number without the dirty script I wrote? I know that Python has a intern min float value, show in sys.float_info.min, which in my PC is 2.22507385851e-308. But I don't see how to use it to solve this problem.
Sorry if this feels more like a puzzle than a proper question, but I'm not able to answer it myself.
I know that Python has a intern min float value, show in sys.float_info.min, which in my PC is 2.22507385851e-308. But I don't see how to use it to solve this problem.
2.22507385851e-308 is not the smallest positive float value, it is the smallest positive normalized float value. The smallest positive float value is 2-52 times that, that is, near 5e-324.
2-52 is called the “machine epsilon” and it is usual to call the “min” of a floating-point type a value that is nether that which is least of all comparable values (that is -inf), nor the least of finite values (that is -max), nor the least of positive values.
Then, the next problem you face is that random.uniform is not uniform to that level. It probably works ok when you pass it a normalized number, but if you pass it the smallest positive representable float number, the computation it does with it internally may be very approximative and lead it to behave differently than the documentation says. Although it appears to work surprisingly ok according to the results of your “dirty script”.
Here's the random.uniform implementation, according to the source:
from os import urandom as _urandom
BPF = 53 # Number of bits in a float
RECIP_BPF = 2**-BPF
def uniform(self, a, b):
"Get a random number in the range [a, b) or [a, b] depending on rounding."
return a + (b-a) * self.random()
def random(self):
"""Get the next random number in the range [0.0, 1.0)."""
return (int.from_bytes(_urandom(7), 'big') >> 3) * RECIP_BPF
So, your problem boils down to finding a number b that will give 0 when multiplied by a number less than 0.5 and another result when multiplied by a number larger than 0.5. I've found out that, on my machine, that number is 5e-324.
To test it, I've made the following script:
from random import uniform
def test():
runs = 1000000
results = [0, 0]
for i in range(runs):
if uniform(0, 5e-324) == 0:
results[0] += 1
else:
results[1] += 1
print(results)
Which returned results consistent with a 50% probability:
>>> test()
[499982, 500018]
>>> test()
[499528, 500472]
>>> test()
[500307, 499693]

Python Loop Help - Calculating PI using Gregory–Leibniz series

I am having an issue getting the python 2.5 shell to do what I need to do. I am trying to have the user input a value for "n" representing a number of times the loop will be repeated. In reality, I need to have the user input N that will correspond to the number of terms from the Gregory–Leibniz series and outputs the approximation of pi.
Gregory–Leibniz series
pi=4*((1/1)-(1/3)+(1/5)-(1/7)+(1/9)-(1/11)+(1/31)...)
So when n is 3,I need the loop calculates up to 1/5. Unfortunately, it is always giving me a value of 0 for the variable of total.
My code as of right now is wrong, and I know that. Just looking for some help. Code below:
def main():
n = int(raw_input("What value of N would you like to calculate?"))
for i in range(1,n,7):
total = (((1)/(i+i+1))-((1)/(i+i+2))+((1)/(i+i+4)))
value = 4*(1-total)
print(value)
main()
This uses integer division, so you will get zero:
total = (((1)/(i+i+1))-((1)/(i+i+2))+((1)/(i+i+4)))
Instead, use floats to get float division.
total = ((1.0/(i+i+1))-(1.0/(i+i+2))+(1.0/(i+i+4)))
In python 2, by default doing / on integers will give you an integer.
In python 3, this has been changed, and / always performed float division (// does integer division).
You need to accumulate terms. e.g.
total = 0.0
term = 1.0
for i in range (1,n+1):
denom = 2*i-1
total += term/denom
term = -term
Of course, you can express this more tersely
It is also more natural perhaps to use this instead
total = 0.0
term = 1.0
for i in range (n):
denom = 2*i+1
total += term/denom
term = -term
As you use the most natural form of of n terms in a range this way. Note the difference in how denominator is calculated.
Q1) Go to https://en.wikipedia.org/wiki/Leibniz_formula_for_%CF%80 to find the Leibniz formula for π. Let S be the sequence of terms that is used to approximate π. As we can see, the first term in S is +1, the second term in S is -1/3 and the third term in S is +1/5 and so on. Find the smallest number of terms such that the difference between 4*S and π is less than 0.01. That is, abs(4*S – math.pi) <= 0.01.

How to add to/subtract from float value the smallest possible value in pure python [explained how is different]?

This question is only for Python programmers. This question is not duplicate not working Increment a python floating point value by the smallest possible amount see explanation bottom.
I want to add/subtract for any float some smallest values which will change this float value about one bit of mantissa/significant part. How to calculate such small number efficiently in pure Python.
For example I have such array of x:
xs = [1e300, 1e0, 1e-300]
What will be function for it to generate the smallest value? All assertion should be valid.
for x in xs:
assert x < x + smallestChange(x)
assert x > x - smallestChange(x)
Consider that 1e308 + 1 == 1e308 since 1 does means 0 for mantissa so `smallestChange' should be dynamic.
Pure Python solution will be the best.
Why this is not duplicate of Increment a python floating point value by the smallest possible amount - two simple tests prove it with invalid results.
(1) The question is not aswered in Increment a python floating point value by the smallest possible amount difference:
Increment a python floating point value by the smallest possible amount just not works try this code:
import math
epsilon = math.ldexp(1.0, -53) # smallest double that 0.5+epsilon != 0.5
maxDouble = float(2**1024 - 2**971) # From the IEEE 754 standard
minDouble = math.ldexp(1.0, -1022) # min positive normalized double
smallEpsilon = math.ldexp(1.0, -1074) # smallest increment for doubles < minFloat
infinity = math.ldexp(1.0, 1023) * 2
def nextafter(x,y):
"""returns the next IEEE double after x in the direction of y if possible"""
if y==x:
return y #if x==y, no increment
# handle NaN
if x!=x or y!=y:
return x + y
if x >= infinity:
return infinity
if x <= -infinity:
return -infinity
if -minDouble < x < minDouble:
if y > x:
return x + smallEpsilon
else:
return x - smallEpsilon
m, e = math.frexp(x)
if y > x:
m += epsilon
else:
m -= epsilon
return math.ldexp(m,e)
print nextafter(0.0, -1.0), 'nextafter(0.0, -1.0)'
print nextafter(-1.0, 0.0), 'nextafter(-1.0, 0.0)'
Results of Increment a python floating point value by the smallest possible amount is invalid:
>>> nextafter(0.0, -1)
0.0
Should be nonzero.
>>> nextafter(-1,0)
-0.9999999999999998
Should be '-0.9999999999999999'.
(2) It was not asked how to add/substract the smallest value but was asked how to add/substract value in specific direction - propose solution is need to know x and y. Here is required to know only x.
(3) Propose solution in Increment a python floating point value by the smallest possible amount will not work on border conditions.
>>> (1.0).hex()
'0x1.0000000000000p+0'
>>> float.fromhex('0x0.0000000000001p+0')
2.220446049250313e-16
>>> 1.0 + float.fromhex('0x0.0000000000001p+0')
1.0000000000000002
>>> (1.0 + float.fromhex('0x0.0000000000001p+0')).hex()
'0x1.0000000000001p+0'
Just use the same sign and exponent.
Mark Dickinson's answer to a duplicate fares much better, but still fails to give the correct results for the parameters (0, 1).
This is probably a good starting point for a pure Python solution. However, getting this exactly right in all cases is not easy, as there are many corner cases. So you should have a really good unit test suite to cover all corner cases.
Whenever possible, you should consider using one of the solutions that are based on the well-tested C runtime function instead (i.e. via ctypes or numpy).
You mentioned somewhere that you are concerned about the memory overhead of numpy. However, the effect of this one function on your working set shout be very small, certainly not several Megabytes (that might be virtual memory or private bytes.)

Categories

Resources