Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I feel so sorry that asked such problem here even though it looks somewhat like a mathematic issue.
The following collision resolution formula appeared in python source code, \pythoncore\Objects\dictobject.c
j = ((5*j) + 1) mod 2**i
The brief description for this formula is For any initial j in range(2*i), repeating that 2*i times generates each
int in range(2*i) exactly once. In an
example that's really too small to make this entirely clear, for a table of
size 2*3 the order of indices is:
0 -> 1 -> 6 -> 7 -> 4 -> 5 -> 2 -> 3 -> 0 [and here it's repeating]
My question is how to prove the correctness of such formula.
The comment you're referring to contains the instruction
see any text on random-number generation for proof
If you search a bit, you'll find that the 5*j+1 mod 2**i recurrence is a linear congruential generator. A linear congruential generator is of the form
x_(n+1) = a*x_n + c (mod m)
For nonzero c, a linear congruential generator has full period (generating all numbers mod m) if and only if
c and m are relatively prime,
a-1 is divisible by all prime factors of m, and
if m is a multiple of 4, a-1 is also a multiple of 4.
This is known as the Hull-Dobell theorem. All these conditions hold for 5*j+1 mod 2**i, so the recurrence goes through all entries in the hash table.
A full proof of the Hull-Dobell theorem can be found here.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
The community reviewed whether to reopen this question 1 year ago and left it closed:
Original close reason(s) were not resolved
Improve this question
I'm trying to make a Pi calculator in python but I need more decimal places.
it would help a lot if someone edited my code and carefully explained what they did.
this is the code I'm using.
import math
d = 0
ans = 0
display = 0
while True:
display += 1
d += 1
ans += 1/d**2
if display == 1000000:
print(math.sqrt(ans*6))
display = 0
# displays value calculated every 1m iterations
output after ~85m iterations: (3.14159264498239)
I need more than 15 decimal places (3.14159264498239........)
You’re using a very slowly converging series for π²∕6, so you are not going to get a very precise value this way. Floating point limitations prevent further progress after 3.14159264498239, but you’re not going to get much further in any reasonable amount of time, anyway. You can get around these issues by some combination of
micro-optimising your code,
storing a list of values, reversing it and using math.fsum,
using decimal.Decimal,
using a better series (like this one),
using a method that converges to the value of π quickly, instead of a series (like this one),
using PyPy, or a faster language than Python,
from math import pi.
you could try with a generator:
def oddnumbers():
n = 1
while True:
yield n
n += 2
def pi_series():
odds = oddnumbers()
approximation = 0
while True:
approximation += (4 / next(odds))
yield approximation
approximation -= (4 / next(odds))
yield approximation
approx_pi = pi_series()
for x in range(10000000):
print(next(approx_pi))
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
ok, I am studying python in my computing course and i have been challenged with designing a code which validates a GTIN-8 code, I have came to a hurdle that i can not jump. I have looked on how to find the equal or higher multiple of a 10 and i have had no success so far, hope you guys can help me!
Here is a small piece of code, i need to find the equal or higher multiple of 10;
NewNumber = (NewGtin_1 + Gtin_2 + NewGtin_3 + Gtin_4 + NewGtin_5 + Gtin_6 + NewGtin_7)
print (NewNumber)
The easiest way, involving no functions and modules, could be using floor division operator //.
def neareast_higher_multiple_10(number):
return ((number // 10) + 1) * 10
Examples of usage:
>>> neareast_higher_multiple_10(15)
20
>>> neareast_higher_multiple_10(21)
30
>>> neareast_higher_multiple_10(20.1)
30.0
>>> neareast_higher_multiple_10(20)
30
We can also make a generalized version:
def neareast_higher_multiple(number, mult_of):
return ((number // mult_of) + 1) * mult_of
If you need nearest lower multiple, just remove + 1:
def neareast_lower_multiple(number, mult_of):
return (number // mult_of) * mult_of
To find the nearest multiple, you can call both these functions and use that one with a lower difference from the original number.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I'm working with the fractions module of python.
I'm trying to get fractions that aproximates 2*.5. The problem is that when I use the Fraction command, it doesn't returns me what I want, because, for example, in i=2, the fractions that returns is 146666667/1000000000, but i want that it returns me 17/12 (The third aproximation of 2*.5). How i can solve it?
The code is this:
ai=2
bi=1
n=5
for i in range(n):
ai=2+float(bi)/ai
F=fr.Fraction(str(ai-1))
print F
Can someone help me, please?
If you are going to work with fractions, don't do part of the calculation with floats. You can perform all the arithmetic with respect to fractions by making ai a Fraction:
import fractions
ai = fractions.Fraction(2)
bi = 1
n = 5
for i in range(n):
ai = 2 + bi / ai
F = ai - 1
print(F)
yields
3/2
7/5
17/12
41/29
99/70
Searching a little bit I found this function limit_denominator(...), that could help you:
F = fr.Fraction(str(ai - 1)).limit_denominator(100)
Output:
3/2
7/5
17/12
41/29
99/70
Read more in Fraction docs.
The fractions module is a great utility. Thanks for bringing it up here.
To control the denominator to more reasonable values, try adding limit_denominator() like this:
from fractions import Fraction
ai=2
bi=1
n=5
for i in range(n):
ai=2+float(bi)/ai
F=Fraction(str(ai-1)).limit_denominator(1000)
print i, F
Output now looks like this:
%run "testFractions.py"
0 3/2
1 7/5
2 17/12
3 41/29
4 99/70
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
Note: I cannot use any of the built in functions to solve this.
This is the question:
Given a function that returns a random integer number between 1 and 5, create a function that creates a random integer between 1 and 7.
As it has been answered in Adam Rosenfield's solution a while ago you may try to use an algoritm similar to this one below:
int i;
do
{
i = 5 * (rand5() - 1) + rand5(); // i is now uniformly random between 1 and 25
} while(i > 21);
// i is now uniformly random between 1 and 21
return i % 7 + 1; // result is now uniformly random between 1 and 7
EDIT: Translation to python:
def rand7():
i = 0;
while True:
i = 5 * (rand5() -1) + rand5()
if i > 21:
break
return i % 7 + 1
Apparently the following doesn't work. See the linked answer and the other responses as well.
Well, here is an approach I am thinking of. It could be wrong. I am going with the assumption that the result should be randomly distributed within the larger range.
Generate 7 random numbers using the given random functions (that generates numbers [1,5]) and calculate their sum.
This will result in a value between 7 (1 * 7) and 35 (5 * 7).
Because this value is evenly divisible by the target range and randomly distributed, then it seems like it would be valid to collapse the intermediate range [7,35] back to [1,7] without losing uniformity.
Or maybe that's not quite it - but it seems like exploiting a common multiple between the numbers is key.
import random
def winningFunc():
return originalFuncReturning1to5() + random.randint(0,2)
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
n=iterations
for some reason this code will need a lot more iterations for more accurate result from other codes, Can anyone explain why this is happening? thanks.
n,s,x=1000,1,0
for i in range(0,n,2):
x+=s*(1/(1+i))*4
s=-s
print(x)
As I mentioned in a comment, the only way to speed this is to transform the sequence. Here's a very simple way, related to the Euler transformation (see roippi's link): for the sum of an alternating sequence, create a new sequence consisting of the average of each pair of successive partial sums. For example, given the alternating sequence
a0 -a1 +a2 -a3 +a4 ...
where all the as are positive, the sequences of partial sums is:
s0=a0 s1=a0-a1 s2=a0-a1+a2 s3=a0-a1+a2-a3 s4=a0-a1+a2-a3+a4 ...
and then the new derived sequence is:
(s0+s1)/2 (s1+s2)/2 (s2+s3)/2 (s3+s4)/2 ...
That can often converge faster - and the same idea can applied to this sequence. That is, create yet another new sequence averaging the terms of that sequence. This can be carried on indefinitely. Here I'll take it one more level:
from math import pi
def leibniz():
from itertools import count
s, x = 1.0, 0.0
for i in count(1, 2):
x += 4.0*s/i
s = -s
yield x
def avg(seq):
a = next(seq)
while True:
b = next(seq)
yield (a + b) / 2.0
a = b
base = leibniz()
d1 = avg(base)
d2 = avg(d1)
d3 = avg(d2)
for i in range(20):
x = next(d3)
print("{:.6f} {:8.4%}".format(x, (x - pi)/pi))
Output:
3.161905 0.6466%
3.136508 -0.1619%
3.143434 0.0586%
3.140770 -0.0262%
3.142014 0.0134%
3.141355 -0.0076%
3.141736 0.0046%
3.141501 -0.0029%
3.141654 0.0020%
3.141550 -0.0014%
3.141623 0.0010%
3.141570 -0.0007%
3.141610 0.0005%
3.141580 -0.0004%
3.141603 0.0003%
3.141585 -0.0003%
3.141599 0.0002%
3.141587 -0.0002%
3.141597 0.0001%
3.141589 -0.0001%
So after just 20 terms, we've already got pi to about 6 significant digits. The base Leibniz sequence is still at about 2 digits correct:
>>> next(base)
3.099944032373808
That's an enormous improvement. A key point here is that the partial sums of the base Leibniz sequence give approximations that alternate between "too big" and "too small". That's why averaging them gets closer to the truth. The same (alternating between "too big" and "too small") is also true of the derived sequences, so averaging their terms also helps.
That's all hand-wavy, of course. Rigorous justification probably isn't something you're interested in ;-)
That is because you are using the Leibniz series and it is known to converge very (very) slowly.