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

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

Related

How do I make an infinite series using an equation?

I'm trying to make a function called cos_series that uses values x and nterms that gives me the sum of a series, using this equation 1 - x^2/2! + x^4/4! - x^6/6! +...
This is my code so far,
def cos_series(x,nterms):
lst = []
lst2 = []
for i in range(nterms):
lst+=[x**(2*i)/(math.factorial(i*2))]
for i in range(nterms):
lst2+=[(x**(2*i)/(math.factorial(i*2)))*-1]
return sum(lst2[1::2] + lst[::2])
cos_series(math.pi/3,3)
The return value should equal 0.501796 but I'm having trouble reaching it, can anyone help?
Your code seems to work just fine.
Your logic works with just:
def cos_series(x, n):
return sum((-1 if (i % 2) else 1) * x**(i*2) / math.factorial(i*2) for i in range(n))
Generating the sum of the series in one go and avoiding the computation of values you don't use.
(note that, after you changed your question, your code in fact returns 0.501796201500181 - which is the value you expected; there's no issue?)
You don't need to use math.factorial() and you don't need to store the terms in a list. Just build the numerator and denominator as you go and add up them up.
By producing the numerator and denominator iteratively, your logic will be much easier to manage and debug:
def cos(x,nTerms=10):
result = 0
numerator = 1
denominator = 1
for even in range(2,nTerms*2+1,2): # nTerms even numbers
result += numerator / denominator # sum of terms
numerator *= -x*x # +/- for even powers of x
denominator *= even * (even-1) # factorial of even numbers
return result
print(cos(3.141592653589793/3,3)) # 0.501796201500181

Floating point Division without using Division Operator

Given two positive floating point numbers x and y, how would you compute x/y to within a specified tolerance e if the division operator
cannot be used?
You cannot use any library functions, such as log and exp; addition
and multiplication are acceptable.
May I know how can I solve it? I know the approach to solving division is to use bitwise operator, but in that approach, when x is less than y, the loop stops.
def divide(x, y):
# break down x/y into (x-by)/y + b , where b is the integer answer
# b can be computed using addition of numbers of power of 2
result = 0
power = 32
y_power = y << power
while x >= y:
while y_power > x:
y_power = y_power>> 1
power -= 1
x = x - y_power
result += 1 << power
return result
An option is to use the Newton-Raphson iterations, known to converge quadratically (so that the number of exact bits will grow like 1, 2, 4, 8, 16, 32, 64).
First compute the inverse of y with the iterates
z(n+1) = z(n) (2 - z(n) y(n)),
and after convergence form the product
x.z(N) ~ x/y
But the challenge is to find a good starting approximation z(0), which should be within a factor 2 of 1/y.
If the context allows it, you can play directly with the exponent of the floating-point representation and replace Y.2^e by 1.2^-e or √2.2^-e.
If this is forbidden, you can setup a table of all the possible powers of 2 in advance and perform a dichotomic search to locate y in the table. Then the inverse power is easily found in the table.
For double precision floats, there are 11 exponent bits so that the table of powers should hold 2047 values, which can be considered a lot. You can trade storage for computation by storing only the exponents 2^0, 2^±1, 2^±2, 2^±3... Then during the dichotomic search, you will recreate the intermediate exponents on demand by means of products (i.e. 2^5 = 2^4.2^1), and at the same time, form the product of inverses. This can be done efficiently, using lg(p) multiplies only, where p=|lg(y)| is the desired power.
Example: lookup of the power for 1000; the exponents are denoted in binary.
1000 > 2^1b = 2
1000 > 2^10b = 4
1000 > 2^100b = 16
1000 > 2^1000b = 256
1000 < 2^10000b = 65536
Then
1000 < 2^1100b = 16.256 = 4096
1000 < 2^1010b = 4.256 = 1024
1000 > 2^1001b = 2.256 = 512
so that
2^9 < 1000 < 2^10.
Now the Newton-Raphson iterations yield
z0 = 0.001381067932
z1 = 0.001381067932 x (2 - 1000 x 0.001381067932) = 0.000854787231197
z2 = 0.000978913251777
z3 = 0.000999555349049
z4 = 0.000999999802286
z5 = 0.001
Likely most straightforward solution is to probably to use Newton's method for division to compute the reciprocal, which may then be multiplied by the numerator to yield the final result.
This is an iterative process gradually refining an initial guess and doubling the precision on every iteration, and involves only multiplication and addition.
One complication is generating a suitable initial guess, since an improper selection may fail to converge or take a larger number of iterations to reach the desired precision. For floating-point numbers the easiest solution is to normalize for the power-of-two exponent and use 1 as the initial guess, then invert and reapply the exponent separately for the final result. This yields roughly 2^iteration bits of precision, and so 6 iterations should be sufficient for a typical IEEE-754 double with a 53-bit mantissa.
Computing the result to within an absolute error tolerance e is difficult however given the limited precision of the intermediate computations. If specified too tightly it may not be representable and, worse, a minimal half-ULP bound requires exact arithmetic. If so you will be forced to manually implement the equivalent of an exact IEEE-754 division function by hand while taking great care with rounding and special cases.
Below is one possible implementation in C:
double divide(double numer, double denom, unsigned int precision) {
int exp;
denom = frexp(denom, &exp);
double guess = 1.4142135623731;
if(denom < 0)
guess = -guess;
while(precision--)
guess *= 2 - denom * guess;
return ldexp(numer * guess, -exp);
}
Handling and analysis of special-cases such as zero, other denormals, infinity or NaNs is left as an exercise for the reader.
The frexp and ldexp library functions are easily substituted for manual bit-extraction of the exponent and mantissa. However this is messy and non-portable, and no specific floating-point representation was specified in the question.
First, you should separate signs and exponents from the both numbers. After that, we'll divide pure positive mantissas and adapt the result using former exponents and signs.
As for dividing mantissas, it is simple, if you'll remember that division is not only inverted multiplication, but also the many-times done substraction. The number of times is the result.
A:B->C, precision e
C=0
allowance= e*B
multiplicator = 1
delta = B
while (delta< allowance && A>0)
if A<delta {
multiplicator*=0.1 // 1/10
delta*=0.1 // 1/10
} else {
A-=delta;
C+=multiplicator
}
}
Really, we can use any number>1 instead of 10. It would be interesting, which will give the most effectivity. Of course, if we use 2, we can use shift instead of multiplication inside the cycle.

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.)

What is wrong with my logic for Project Euler 71?

Right now I am trying to solve Project Euler 71.
Consider the fraction, n/d, where n and d are positive integers. If
n
If we list the set of reduced proper fractions for d ≤ 8 in ascending
order of size, we get:
1/8, 1/7, 1/6, 1/5, 1/4, 2/7, 1/3, 3/8, 2/5, 3/7, 1/2, 4/7, 3/5, 5/8,
2/3, 5/7, 3/4, 4/5, 5/6, 6/7, 7/8
It can be seen that 2/5 is the fraction immediately to the left of
3/7.
By listing the set of reduced proper fractions for d ≤ 1,000,000 in
ascending order of size, find the numerator of the fraction
immediately to the left of 3/7.
The Current Code:
from fractions import Fraction
import math
n = 428572
d = 1000000
x = Fraction(3,7)
best = Fraction(0)
while d > 1:
if Fraction(n,d) >= x:
n-=1
else:
y = Fraction(n,d)
if (x - y) < (x - best):
best = y
d -= 1
n = int(math.ceil(d*0.428572))
print(best.denominator)
Explanation:
from fractions import Fraction
import math
Needed for Fractions and math.ceil.
n = 428572
d = 1000000
These two variables represent the n and d stated in the original problem. The numbers start out this way because this is a slightly bigger representation of 3/7 (will be converted to Fraction later).
x = Fraction(3,7)
best = Fraction(0)
x is just a quick reference to Fraction(3,7) so I don't have to keep typing it. best is used to keep track what fraction is closest to 3/7 but still left of it.
while d > 1:
If d <= 1 and n has to be less than 1 what is the point of checking? Stop check then.
if Fraction(n,d) >= x:
n-=1
If the fraction ends up being bigger than or equal to 3/7 it isn't to the left of it, so keep subtracting from n till it is to the left of 3/7.
else:
y = Fraction(n,d)
if (x - y) < (x - best):
best = y
If it is to the left of 3/7 see if 3/7 minus best or y (which is equal to the fraction we need to check) is closer to 0. The one closer to zero will be the least left, or closest to 3/7.
d -= 1
n = int(math.ceil(d*0.428572))
Regardless of whether best changes or not, the denominator needs to be changed. So subtract one from the denominator and set n the Fraction(n,d) slightly greater (added extra ceil method to make sure it is greater!) than 3/7 to prune the test space.
print(best.denominator)
Finally print what the question wants.
Note
Changing d to 8 and n to 4 (like the test case) gives the desired result of 5 for the denominator. Keeping it as is gives: 999997.
Can someone please explain to me what I am doing wrong?
This isn't the correct way to do things. You are supposed to use the Stern-Brocot tree. You shouldn't have to mess around with floating points at all.
What you are doing wrong:
find the numerator
Apart from that, follow #Antimony's advice and learn about the Stern-Brocot tree, that's useful and fun.
Not to make you feel stupid. But your answer is perfectly correct, read the question again and change the last line to:
print( best.numerator )
Also, for the record there is a MUCH more efficient way of calculating this.

Categories

Resources