Forum: PC-Programmierung Python: Generator für E-Reihen


von Tom K. (ez81)


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

von Tom K. (ez81)


Angehängte Dateien:

Lesenswert?

Anhang ging nicht.

von Yalu X. (yalu) (Moderator)


Angehängte Dateien:

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"

von Stefan Salewski (Gast)


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.

von Stefan Salewski (Gast)


Angehängte Dateien:

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

von Yalu X. (yalu) (Moderator)


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.

von Ingo B. (Gast)


Lesenswert?

Du kannst die E-Reihe nicht mit einer Formel ausrechnen.
Das sieht man bei Wikipedia ( siehe Link oben ), wenn man auf 
Diskussionen
geht ist dort ein einfacher Java Code, der nach der angegebenen Formel
die Werte der E-Reihe bestimmt und ausgibt.
Es sind dann die Werte markiert, die von der ( realen ) E-Reihe 
abweichen.

von Yalu X. (yalu) (Moderator)


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

von Tom K. (ez81)


Lesenswert?

Vielen Dank! Die Zauberei mit itertools muss ich mir mal genauer 
ansehen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.