np.arange macht was es will

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
Sebbastiannn
User
Beiträge: 6
Registriert: Mittwoch 15. Juni 2022, 22:05

Hallo Zusammen:)

Ich bekomme einen seltsamen Output bei diesen Quellcode und ich weiß nicht wie ich es lösen kann :/
Beim Fall 1 bei A bekomme ich:

[ 1.80000000e+00 1.78000000e+00 1.76000000e+00 1.74000000e+00
1.72000000e+00 1.70000000e+00 1.68000000e+00 1.66000000e+00
1.64000000e+00 1.62000000e+00 1.60000000e+00 1.58000000e+00
1.56000000e+00 1.54000000e+00 1.52000000e+00 1.50000000e+00
.......
1.20000000e-01 1.00000000e-01 8.00000000e-02 6.00000000e-02
4.00000000e-02 2.00000000e-02 -1.55431223e-15 -2.00000000e-02
-4.00000000e-02 -6.00000000e-02 -8.00000000e-02 -1.00000000e-01]

Was okay ist, aber im Fall 1 bei B geht er bis -1.02 ? Obwohl ich ihm genau das Gleiche sage wie bei A? woher kommen die extra -1.02 am Ende?
Wenn ich eingebe:

Code: Alles auswählen

np.arange(startA1,endA1,stepA1)
statt

Code: Alles auswählen

np.arange(startA1,endA1+stepA1,stepA1)
dann geht er nur bis bis -0.98 was logisch ist. Aber eig erwarte ich dann bei endA1+stepA1 das er bis -1 geht und nicht bis -1.02, da er die letzte Zahl nicht nimmt, aber jetzt irgendwie schon?! :o
Hat jemand eine Idee wie man das lösen kann?
Beste Grüße,
Basti

[ 1.00000000e-01 8.00000000e-02 6.00000000e-02 4.00000000e-02
2.00000000e-02 -1.38777878e-17 -2.00000000e-02 -4.00000000e-02
-6.00000000e-02 -8.00000000e-02 -1.00000000e-01 -1.20000000e-01
.....
-7.80000000e-01 -8.00000000e-01 -8.20000000e-01 -8.40000000e-01
-8.60000000e-01 -8.80000000e-01 -9.00000000e-01 -9.20000000e-01
-9.40000000e-01 -9.60000000e-01 -9.80000000e-01 -1.00000000e+00
-1.02000000e+00]

Hier der Quellcode:

Code: Alles auswählen

import numpy as np
"""
First Case
"""
startA1     =   -1.8
endA1       =   0.1
stepA1      =   0.02

startB1     =   -0.1
endB1       =   1
stepB1      =   0.02

voltageA1 = []
voltageB1 = []

if startA1 < endA1:
    voltageA1 = -np.arange(startA1,endA1+stepA1,stepA1)
    print(voltageA1)
else:
    voltageA1 = -np.arange(startA1,endA1+stepA1,-stepA1)
    print(voltageA1)
      
if startB1 < endB1:
   voltageB1 = -np.arange(startB1,endB1+stepB1,stepB1)
   print(voltageB1)
else:
    voltageB1 = -np.arange(startB1,endB1+stepB1,-stepB1)
    print(voltageB1)
    
"""
Second Case
"""   
    
startA2     =   -1.8
endA2       =   0.1
stepA2      =   0.02

startB2     =   -0.1
endB2       =   1
stepB2      =   0.02

voltageA2 = []
voltageB2 = []

if startA2 < endA2:
    voltageA2 = -np.arange(startA2,endA2+stepA2,stepA2)
    print(voltageA2)
else:
    voltageA2 = -np.arange(startA2,endA2-stepA2,-stepA2)
    print(voltageA2)
      
if startB2 < endB2:
   voltageB2 = -np.arange(startB2,endB2+stepB2,stepB2)
   print(voltageB2)
else:
    voltageB2 = -np.arange(startB2,endB2-stepB2,-stepB2)
    print(voltageB2)
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

Floatzahlen haben eine endliche Genauigkeit. Das siehst du an -1.38777878e-17 statt der 0. So ist auch 1.02 in Wirklichkeit etwas kleiner.
Bei arange kann man eigentlich nur mit ganzen Zahlen richtig arbeiten. Nimm linspace. Das macht auch deine Fallunterscheidungen überflüssig.
Sebbastiannn
User
Beiträge: 6
Registriert: Mittwoch 15. Juni 2022, 22:05

Hi:)

wenn ich aber np.linspace benutze bekomme ich immer eine Fehlermeldung das:
TypeError: 'float' object cannot be interpreted as an integer
Wie würdest du es machen das ich Werte raus bekomme wie:
[-1.8, -1.78, -1.76 .... 0.06, 0.08, 0.1]

bei:

Code: Alles auswählen

import numpy as np

startA1     =   -1.8
endA1       =   0.1
stepA1      =   0.02
numA1       =   (abs(startA1)+abs(endA1))/stepA1
print(numA1)

voltageA1 = []
voltageA1 = -np.linspace(startA1,endA1,numA1)
print(voltageA1)
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Na du musst doch eine diskrete Anzahl von Elementen erzeugen. Entsprechend muss deine numA1 ein integer sein.
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

Wie Du Deine Anzahl an Werten berechnest ist falsch.
Die Formel ist Ende - Start geteilt durch Schrittweite. Dann noch Runden und Betrag nehmen, damit man eine positive ganze Anzahl hat.
Das Initialisieren von voltageA1 mit einer leeren Liste ist unnötig, da die nie benutzt wird.
Benutzeravatar
Dennis89
User
Beiträge: 1156
Registriert: Freitag 11. Dezember 2020, 15:13

Hallo,

das könnte am dritten Argument liegen, dass du da übergibst:
https://numpy.org/doc/stable/reference/ ... y.linspace

Grüße
Dennis

__deets__ war schneller, ich antworte trotzdem dann hast du den Link noch.
Edit: und Sirius3 war auch schneller
"When I got the music, I got a place to go" [Rancid, 1993]
Benutzeravatar
__blackjack__
User
Beiträge: 13117
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Sebbastiannn: Siehe auch http://floating-point-gui.de

Anmerkungen zum Quelltext: Literale Zeichenketten sind keine Kommentare. Auch mehrzeilige Kommentare setzt man mit #. Halt vor jeder Zeile. Jeder brauchbare Editor hat da auch ein Tastenkürzel um mehrere ausgewählte Zeilen aus-/einzukommentieren. Also:

Code: Alles auswählen

"""
First Case
"""

# =>

#
# First Case
#
Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (PascalCase).

Ausrichten an Gleichheitszeichen/Operatoren und so weiter macht man nicht. Das zieht nur unnötig Arbeit nach sich wenn sich ein Teil in der Länge verändert und man deshalb dann andere, eigentlich unbetroffene Zeilen mit ändern muss. Das verdeckt dann in Diffs noch zusätzlich die eigentlichen Änderungen.

Nach Kommas, um Gleicheitszeichen (ausserhalb von Aufruflisten) und binäre Operatoren erhöhen Leerzeichen die Lesbarkeit.

Siehe auch Style Guide for Python Code.

Quelltext kopieren, einfügen, und leicht verändern sollte man auch nicht machen. Das ist unnötig aufwändig und fehleranfällig wenn man dann später etwas korrigieren, ändern, oder erweitern muss, und das bei allen Kopien machen muss, und es überall gleich, oder zumindest äquivalent, ändern muss. Zum Beispiel die Einrückung von dem einen ``else``-Zweig anpassen bei dem nur drei statt vier Leerzeichen verwendet wurden.

Statt Code und Daten kopieren verwendet man Funktionen und Schleifen.

Auch für das Vereinfachen muss man unnötig viel Zeit in alle Kopien stecken. Wenn an am Anfang oder Ende aller ``if``/``elif``/``else``-Zweige gleicher Code ausgeführt wird, dann gehört der *einmal* vor beziehungsweise hinter das Konstrukt, statt in jeden Zweig.

Die Listen die an die `voltage_*`-Namen gebunden werden, werden nirgends verwendet. Diese Zeilen sind also überflüssig. Was den Typ angeht, ist es grenzwertig und kommt darauf an wie die Werte hinterher verwendet werden. Falls der Code mit jeder Art von Sequenz klar kommt, oder gar nur iterierbare Objekte braucht, dann ist es okay mal Listen und mal Numpy-Arrays an den gleichen Namen zu binden, weil die dann den gleichen „duck typ“ haben. Sollte folgender aber Code Eigenschaften von Numpy-Arrays verwenden die Listen nicht bieten, dann sollte man keine Listen an die Namen binden.

Wenn man die Unterschiede aus den vier Kopien in Datenstrukturen heraus zieht und eine gemeinsame Funktion schreibt, könnte das so aussehen:

Code: Alles auswählen

#!/usr/bin/env python3
import numpy as np


def create_array(start, end, step, add_step_if_reversed):
    if start < end:
        end += step
    else:
        end = end + step if add_step_if_reversed else end - step
        step = -step

    return -np.arange(start, end, step)


def main():
    for add_step_if_reversed in [True, False]:
        for start, end, step in [(-1.8, 0.1, 0.02), (-0.1, 1, 0.02)]:
            print(create_array(start, end, step, add_step_if_reversed))


if __name__ == "__main__":
    main()
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Sebbastiannn
User
Beiträge: 6
Registriert: Mittwoch 15. Juni 2022, 22:05

Also erstmal danke für die ganzen Tipps:))

@__deets__ und @Sirius3:
Okay also wenn ich die Anzahl als Integer eingebe fkt es, allerdings bekomme ich dann immer noch das hier raus:
array([-1.80000000e+00, -1.77978723e+00, -1.75957447e+00, -1.73936170e+00,
-1.71914894e+00, -1.69893617e+00, -1.67872340e+00, -1.65851064e+00,
-1.63829787e+00, -1.61808511e+00, -1.59787234e+00, -1.57765957e+00,
...
-1.02127660e-01, -8.19148936e-02, -6.17021277e-02, -4.14893617e-02,
-2.12765957e-02, -1.06382979e-03, 1.91489362e-02, 3.93617021e-02,
5.95744681e-02, 7.97872340e-02, 1.00000000e-01])

Bei der Rechnung stimmt in diesen Fall eig alles numA1= (|-1.8|+|0,1|)/0,02 = 95 und wenn ich das Eintrage in Python

voltageA1 = np.linspace(startA1, endA1, numA1, retstep=True)
also startA1=-1.8 endA1=0,1 und numA1=95, dann teilt er 1,9/95 =0,02 also alles richtig, wenn ich jetzt noch retstep=true mache kommt aber raus als Spepsize =0.02021276595744681 :?

außerdem habe ich gemerkt das es ein voltageA1 = Array([...]) Format hat, allerdings brauche ich das gleiche Format wie bei np.arange, dass es einfach nur eine Liste ist ->voltageA1 = [...]

@__blackjack__
Dir auch denke für die ganzen Tipps und den Code, der ist schon deutlich optimiert!! :)
Allerdings macht der Code immer noch ein Step zuviel und wir landen bei 1.20000000e-01 obwohl er bei 1.00000000e-01 aufhören sollte.

Ich überlege gerade ob ich es einfach ganz normal mache mit np.arange und danach schaue ob einer der letzte Werte der Liste über den Endwert hinausgeht und den enifach lösche.
Füllt sich total falsch an es so zu machen und wurde mich selber dafür hauen, aber am Ende muss es nur fkt und nicht durchoptimiert sei:) Also sind auch die hässlichen Lösungen erstmal okay solange es funktioniert.
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

Das ist wie mit dem 50 m Gartenzaun. Du brauchst 51 Pfosten. Und wenn du hier den Endwert mitnimmst brauchst du eine Zahl mehr, also 96.
Sebbastiannn
User
Beiträge: 6
Registriert: Mittwoch 15. Juni 2022, 22:05

:lol: oh man okay ja du hast recht haha
Ich werde es mal alles kurz in den Hauptcode implementieren und dann schauen ob es noch fkt:)

Danke euch allen!!!
Benutzeravatar
__blackjack__
User
Beiträge: 13117
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Sebbastiannn: Mein Quelltext sollte genau das gleiche machen wie Deiner, es ging ja nur darum was man daran verbessern kann.

Auch `np.arange()` liefert keine Liste sondern ein Numpy-Array. Wenn das vorher kein Problem war, dann sollte der Ergebnistyp von `np.linspace()` auch kein Problem sein.

Da ist der Endpunkt mit drin, dann stimmt die Rechnung ja auch nicht. Du musst entweder 96 Elemente erzeugen, oder 95 Element aber ohne Endpunkt, wenn Du eine Schrittweite von 0.02 haben willst:

Code: Alles auswählen

In [153]: np.linspace(-1.8, 0.1, 96, retstep=True)                              
Out[153]: 
(array([-1.8 , -1.78, -1.76, -1.74, -1.72, -1.7 , -1.68, -1.66, -1.64,
        -1.62, -1.6 , -1.58, -1.56, -1.54, -1.52, -1.5 , -1.48, -1.46,
        -1.44, -1.42, -1.4 , -1.38, -1.36, -1.34, -1.32, -1.3 , -1.28,
        -1.26, -1.24, -1.22, -1.2 , -1.18, -1.16, -1.14, -1.12, -1.1 ,
        -1.08, -1.06, -1.04, -1.02, -1.  , -0.98, -0.96, -0.94, -0.92,
        -0.9 , -0.88, -0.86, -0.84, -0.82, -0.8 , -0.78, -0.76, -0.74,
        -0.72, -0.7 , -0.68, -0.66, -0.64, -0.62, -0.6 , -0.58, -0.56,
        -0.54, -0.52, -0.5 , -0.48, -0.46, -0.44, -0.42, -0.4 , -0.38,
        -0.36, -0.34, -0.32, -0.3 , -0.28, -0.26, -0.24, -0.22, -0.2 ,
        -0.18, -0.16, -0.14, -0.12, -0.1 , -0.08, -0.06, -0.04, -0.02,
         0.  ,  0.02,  0.04,  0.06,  0.08,  0.1 ]),
 0.02)

In [154]: np.linspace(-1.8, 0.1, 95, endpoint=False, retstep=True)              
Out[154]: 
(array([-1.8 , -1.78, -1.76, -1.74, -1.72, -1.7 , -1.68, -1.66, -1.64,
        -1.62, -1.6 , -1.58, -1.56, -1.54, -1.52, -1.5 , -1.48, -1.46,
        -1.44, -1.42, -1.4 , -1.38, -1.36, -1.34, -1.32, -1.3 , -1.28,
        -1.26, -1.24, -1.22, -1.2 , -1.18, -1.16, -1.14, -1.12, -1.1 ,
        -1.08, -1.06, -1.04, -1.02, -1.  , -0.98, -0.96, -0.94, -0.92,
        -0.9 , -0.88, -0.86, -0.84, -0.82, -0.8 , -0.78, -0.76, -0.74,
        -0.72, -0.7 , -0.68, -0.66, -0.64, -0.62, -0.6 , -0.58, -0.56,
        -0.54, -0.52, -0.5 , -0.48, -0.46, -0.44, -0.42, -0.4 , -0.38,
        -0.36, -0.34, -0.32, -0.3 , -0.28, -0.26, -0.24, -0.22, -0.2 ,
        -0.18, -0.16, -0.14, -0.12, -0.1 , -0.08, -0.06, -0.04, -0.02,
         0.  ,  0.02,  0.04,  0.06,  0.08]),
 0.02)
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten