1 | from math import log10, ceil
|
2 | from itertools import tee, count, takewhile, dropwhile, izip, chain, imap
|
3 |
|
4 | # von Yalu: http://www.mikrocontroller.net/topic/261919#2718301
|
5 |
|
6 | def e_series(ser, low, high, adj=False):
|
7 | '''
|
8 | generate a range of E<ser> values
|
9 | low: lower bound
|
10 | high: upper bound (must be >= low)
|
11 | ser: one of 3, 6, 12, 24, 48, 96, 192, ...
|
12 | adj: if True, adjacent values below low and above high are generated too
|
13 | '''
|
14 |
|
15 | # avoid unlovely effects due to rounding errors
|
16 | low *= 1 - 1e-15
|
17 | high *= 1 + 1e-15
|
18 |
|
19 | if ser < 48:
|
20 | # for E3 to E24: crappy "quasi"-exponential series rounded to 1 digit
|
21 | series = [round(10**(i/24.)-abs(i-11)/90.+.1, 1) for i in range(0, 24, 24/ser)]
|
22 | else:
|
23 | # for E48 and higher: clean exponential series rounded to 2 digits
|
24 | series = [round(10**(i/192.)+i**3*4e-11, 2) for i in range(0, 192, 192/ser)]
|
25 | # some magic stuff from itertools follows:
|
26 |
|
27 | # generate two infinite sequences of ascending values, displaced by one element
|
28 | g0,g1 = tee(val*10**i for i in count(int(ceil(log10(low)))-1) for val in series)
|
29 | g1.next()
|
30 |
|
31 | # zip both sequences together and take all elements between the given bounds
|
32 | g = takewhile(lambda (x0,x1): x0<=high, dropwhile(lambda (x0,x1): x1<low, izip(g0, g1)))
|
33 | first = g.next()
|
34 |
|
35 | # if adj=False, return all values in [low,high] else add two extra values
|
36 | return chain(first, imap(lambda (x0,x1): x1, g)) if adj else imap(lambda (x0,x1): x0, g)
|
37 |
|
38 |
|
39 | if __name__ == '__main__':
|
40 | for r in e_series(3, .004, 3000, True):
|
41 | print r,
|
42 | print
|