Python: Generator für E-Reihen

#2717556
Lesenswert?

Hallo liebe Experten,

ich brauche etwas, das die Werte der E-Reihen in einem bestimmten 
Wertebereich listet und habe das nachstehende zusammengefrickelt:
1
def e_series(ser, minimum, maximum):
2
    '''
3
    values of the E<ser>-series from minimum to maximum.
4
    ser may be =6, 12, 24, 48, 96
5
    '''
6
    # vollstaendiger code im anhang
7
    series = {6: [1.0, 1.5, 2.2, 3.3, 4.7, 6.8],
8
         12: [1.0, 1.2, 1.5, 1.8, 2.2, 2.7, 3.3, 3.9, 4.7, 5.6, 6.8, 8.2]}
9
    base_decade = 10.0 ** int(math.log10(minimum) - 1)
10
    top_decade =  10.0 ** (int(math.log10(maximum)) + 1)
11
    decade = base_decade
12
    while decade <= top_decade:
13
        for factor in series[ser]:
14
            value = decade * factor
15
            if minimum <= value <= maximum:
16
                yield value
17
        decade *= 10
18

19
if __name__ == '__main__':
20
    for i in e_series(12, 0.1001, 6):
21
        print i,
22
    print
Die Ausgabe ist '0.12 0.15 0.18 0.22 0.27 0.33 0.39 0.47 0.56 0.68 0.82 
1.0 1.2 1.5 1.8 2.2 2.7 3.3 3.9 4.7 5.6'.

Ich würde das ganze gerne so erweitern, dass der Wert davor und der 
danach (also 0.1 und 6.2) optional auch geliefert werden können und 
stehe irgendwie auf dem Schlauch. Hat jemand eine Idee?

Alle Verbesserungsvorschläge und elegantere Lösungen sind auch höchst 
willkommen, der Code oben hat einige sehr hässliche Stellen, z.B. 'if 
minimum <= value <= maximum:' und die Berechnung der Dekaden.

Grüße,
Tom

EDIT: Effizienz ist in diesem Fall ziemlich egal, Wenn auf einem 
Core2Duo ein Wert pro Sekunde rauskommt, wäre das auch noch ausreichend 
;)
Moderator #2718301
Lesenswert?

Hab mal was ziemlich Generatorisches zusammengefrickelt (e_series.py).
Die optionalen Davor- und Danach-Werte erfordern allerdings leichte
Verrenkungen. Deswegen habe ich noch eine vereinfachte Version ohne
diesen Zusatz hochgeladen (e_series_simple.py). Sie entspricht im
Wesentlichen deiner ursprünglichen Version, unterstützt aber alle
E<k>-Reihen mit k=3·2^n, also E3, E6, E12, E24, E48, E96, E192 usw.

Edit: Da ist noch ein Fehler drin. Korrektur siehe

  Beitrag "Re: Python: Generator für E-Reihen"
Angehängte Dateien:
Gast #2718445
Lesenswert?

>Hab mal was ziemlich Generatorisches zusammengefrickelt

Hm. Und Du hast die berechneten Werte alle mit den Normwerten 
verglichen?
Ich hatte leider nie eine genaue Vorschrift für die Rundung gefunden -- 
bei Wikipedia heißt es "Die Glieder der Folge werden so gerundet, dass 
sich bei den Reihen E3 bis E24 zwei und bei den Reihen E48 bis E192 drei 
signifikante Stellen und außerdem zwischen benachbarten Folgengliedern 
minimale Differenzen ergeben." Was gemeint ist, ist mir zwar vom Prinzip 
klar, aber nicht so recht, wie man das konkret realisieren soll. Es gibt 
jedenfalls Aussagen, dass die E-Reihen recht willkürlich sind und nicht 
wirklich berechnet werden können. Zumindest heißt es bei Wikipedia ja 
auch "entsprechen in der E24-Reihe die Werte von 2,7 bis 4,7 nicht den 
Rundungsregeln".

Na gut, Dir traue ich durchaus eine richtige Lösung zu.

Was ich mal machen wollte: Ein Skript, wo man einen gewünschte Wert und 
die zulässige Toleranz eingibt und dann passende E-Reihen-Werte bekommt.
Gast #2718566
Lesenswert?

>Hm. Und Du hast die berechneten Werte alle mit den Normwerten
>verglichen?

Nun ja, es sieht ja schon recht gut aus.
Allerdings gibt dein Script mit der geänderten Zeile

>for r in e_series(192, 100, 1000, True):

bei mir dem Wert 919.0 aus.
Nach Wikipedia sollte das eher 920 sein.

http://de.wikipedia.org/wiki/E-Reihe

Ich habe mal die Werte von

http://en.wikipedia.org/wiki/Preferred_number#E_series:_Capacitors_and_resistors

zusammen kopiert, siehe Anhang. Mit
cut --fields=4 E-Reihen.txt |grep "\S"
bekommt man die einzelnen Reihen unter Unix, fields= kann 1 bis 6 sein 
je nach Reihe. Mit diff kann man dann die Werte mit dem Python-Script 
vergleichen. Na ja wer mag, ich kenne mich besser mit Ruby als mit 
Python aus...
Angehängte Dateien:
Moderator #2719196
Lesenswert?

Mist, du hast recht :-/

Die E24-Reihe habe ich kontrolliert. Dafür eine Formel zu finden, war 
auch nicht ganz leicht, weil die Werte teilweise ziemlich willkürlich 
augewählt worden sind. Auf jeden Fall stimmen damit auch E12, E6 und E3.

Für E48 und darüber habe ich einmal gelesen, dass diese einfach durch 
Runden der Werte der entsprechenden Exponentialfunktion ergeben und habe 
sie deswegen nur stichprobenweise kontrolliert. Anscheinend war aber 
diese Information falsch bzw. das zu verwendende Rundungverfahren ist 
ein komplizierteres. Es ist wohl so, dass bei der Rundung nicht nur der 
jeweils aktuelle Wert, sondern auch die beiden Nachbarn mit einbezogen 
werden, um einen möglichst gleichmäßigen Verlauf zu erhalten.

Da müsste ich also noch einmal darübergehen :)
Im Moment habe ich nur keinen PC hier.
Moderator #2720135
Lesenswert?

Ich habe die Werte nun für alle E-Reihen komplett überprüft. Der von
Stefan gefundene Fehler

Stefan Salewski schrieb:
> bei mir dem Wert 919.0 aus.
> Nach Wikipedia sollte das eher 920 sein.

war der einzige.

Der rechnerische Wert 9,19 in der E192-Reihe hat die unschöne Eigen-
schaft, dass sich seine Abstände zum Vorgänger (9,09) und Nachfolger
(9,31) um 2 unterscheiden. Für alle anderen Werte in der Reihe beträgt
dieser Unterschied maximal 1. Das ist wohl der Grund, warum der Wert in
der offiziellen E192-Reihe durch 9,20 ersetzt wurde.

Ersetzt man in den obigen Programmen die Zeile 22
1
  series = [round(10**(i/float(ser)), 2) for i in range(ser)]

durch
1
  series = [round(10**(i/192.)+i**3*4e-11, 2) for i in range(0, 192, 192/ser)]

sind alle Werte in E3, E6, E12, E24, E48, E96 und E192 korrekt.

Ich gebe zu: Ein wenig hingemurkst ist es ja schon :)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren