<p>numpy.isclose vs math.isclose</p>

Erstellt am 5. Dez. 2017  ·  78Kommentare  ·  Quelle: numpy/numpy

numpy.isclose (https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.isclose.html):

abs(a - b) <= (atol + rtol * abs(b))

math.isclose (https://docs.python.org/3/library/math.html#math.isclose):

abs(a - b) <= max(rtol * max(abs(a), abs(b)), atol)

Beachten Sie, dass die Numpy-Gleichung nicht symmetrisch ist und die Parameter atol und rtol korreliert. Beide sind schlechte Dinge (IMO).

Hier ist eine Situation, in der Numpy "falsch" zwei Zahlen als gleich kennzeichnet:

a = 0.142253
b = 0.142219
rtol = 1e-4
atol = 2e-5

# true because atol interferes with the rtol measurement
abs(a - b) <= (atol + rtol * abs(b))
Out[24]: True

# correct result, rtol fails
abs(a - b) <= max(rtol * max(abs(a), abs(b)), atol)
Out[29]: False

Hier ist ein anderes, dieses Fall-Symmetrie-Problem:

a = 0.142253
b = 0.142219
rtol = 1e-4
atol = 1.9776e-05

# relative to b
abs(a - b) <= (atol + rtol * abs(b))
Out[73]: False

#relative to a
abs(a - b) <= (atol + rtol * abs(a))
Out[74]: True

# math one has no problems with this
abs(a - b) <= max(rtol * max(abs(a), abs(b)), atol)
Out[75]: False

Die Python-Mathe-Version scheint kugelsicher zu sein. Sollte Numpy damit beginnen? Gibt es irgendwelche Vorteile bei der Verwendung der Numpy-Version?

57 - Close?

Hilfreichster Kommentar

@njsmith : Danke, dass du mich

Ein bisschen Geschichte: Als ich vorgeschlagen habe, die stdlib zu schließen, haben wir numpy sicherlich als Stand der Technik angesehen. Wenn es nur ich wäre, hätte ich möglicherweise einen kompatiblen Ansatz verwendet, um die Kompatibilität zu gewährleisten :-).

Aber der Rest der Community dachte, es sei wichtiger, das zu tun, was für Python "richtig" war, und so folgte eine lange Diskussion ... Ich habe versucht, den größten Teil des PEP-Punktes zu erfassen, wenn Sie nachsehen möchten.

Hier ist der Verweis auf numpy:

https://www.python.org/dev/peps/pep-0485/#numpy -isclose

Sie können sehen, dass die gleichen Punkte wie in dieser Diskussion gemacht wurden.

Am Ende kamen drei wichtige Punkte heraus:

1) Ein symmetrischer Ansatz würde die geringste Überraschung zur Folge haben.

2) Die absolute Standardtoleranz sollte wahrscheinlich Null sein, um keine Annahmen über die Größenordnung der Argumente zu treffen.

3) Der Unterschied zwischen den "schwachen" und "starken" Tests war irrelevant, wenn er mit kleinen Toleranzen verwendet wurde, wie dies der erwartete Anwendungsfall ist.

Am Ende haben wir die "beste" Lösung für math.isclose gefunden.

Aber ist es "besser" genug, um die Abwärtskompatibilität zu brechen? Das glaube ich nicht.

Leider wurden vielen Numpy (und Python) viele Funktionen hinzugefügt, weil sie nützlich waren, aber ohne viel aktuelle Diskussion werden diese Dinge, so dass wir viele suboptimale Designs haben. Dies wird für eine junge Bibliothek erwartet (und ist notwendig), und wir müssen jetzt nur damit leben.

@njsmith ist richtig - Ich denke, nur sehr wenige Anwendungen von np.isclose () haben die Toleranzen, die durch eine strenge FP-Fehleranalyse festgelegt wurden, sondern versuchen einen Fehler mit np.isclose () selbst.

Ich denke jedoch, dass das größere Problem die Standardeinstellung atol - es wird davon ausgegangen, dass Ihre Argumente in der Größenordnung 1 liegen - was eine SEHR falsche Annahme sein könnte und da dies häufig dazu führen würde, dass Tests bestanden werden, sollte dies nicht der Fall sein Benutzer bemerken es möglicherweise nicht.

In [85]: np.isclose(9.0e-9, 1.0e-9)
Out[85]: True

Autsch!

und ja, es sind die atol die dies verursachen:

In [86]: np.isclose(9.0e-9, 1.0e-9, atol=0.0)
Out[86]: False

Es ist also wahrscheinlich eine gute Idee, einen Weg nach vorne zu finden.

Ich mag die Idee mit dem Schlüsselwortargument - scheint viel einfacher zu sein, als mit __future__ und dergleichen zu spielen.

Und wir könnten dann entscheiden, ob wir mit der Ausgabe von Verfallswarnungen beginnen und letztendlich die Standardversion vieler nachgelagerter Versionen ändern möchten ...

Alle 78 Kommentare

Zu spät, um etwas imho zu ändern.

Dies ist eine der am häufigsten verwendeten Funktionen in ganz numpy (bis assert_allclose ). Der einzige Weg hierfür wäre die Auswahl eines anderen Namens.

Ich gebe zu, dass die aktuelle Implementierung wie ein Fehler aussieht. Beachten Sie, dass die Verwendung von max(abs(a), abs(b)) anstelle von abs(b) keine vorhandenen Tests unterbricht, sondern lediglich die Bedingung für den Fall lockert, dass abs(a) > abs(b) .

Zumindest erfordert dies eine Warnung in der Dokumentzeichenfolge, dass die eingebaute Datei nicht übereinstimmt

Wie wäre es damit?

from numpy.__future__ import isclose

Das könnte übrigens eine Idee für die Versionierung von Zufallszahlen sein ...

Zur Verdeutlichung würde der Import nicht isclose importieren, sondern die neue Semantik ermöglichen. Es würde zu einem Modul geschöpft.

Die Idee ist, dass wir Menschen erlauben können, die richtige Funktion zu verwenden, und gleichzeitig keinen vorhandenen Code brechen müssen.

würde der Import nicht tatsächlich isclose importieren, sondern die neue Semantik ermöglichen

Ich denke nicht, dass es möglich ist, dies nicht zu importieren. Wählen Sie einfach einen längeren Namen wie mathlike_ufunc s, der auch remainder abdecken könnte.

Beachten Sie, dass from __future__ import print_function tatsächlich ein print_function global erzeugt

Tatsächlich ist der Importstil von from __future__ import * hier möglicherweise nicht angemessen - in Python wirkt er sich auf _syntax_ auf Dateiebene aus, und es wäre schwierig, in numpy etwas Ähnliches zu tun

Die Iteratorausnahmen waren keine Syntaxänderung. Wir brauchen nur ein kleines C-Modul, um den Namespace des aufrufenden Moduls zu überprüfen. Wir können die Module sogar zwischenspeichern, sodass nur die Importzeit verlangsamt wird und dies nur trivial ist.

Sie haben Recht - und true_division ist offensichtlich analog zu isclose.

Dies ist eine gute Möglichkeit, um die Probleme in # 9444 zu vermeiden, als Alternative zur Verwendung von with -Anweisungen zum Verwalten veralteter Features.

Lassen Sie uns CC @ ChrisBarker-NOAA als Schöpfer von math.isclose .

Dies ist ein ziemlich kleines Problem IMO. Im Allgemeinen werden atol und rtol ausgewählt, indem Sie mit ihnen herumspielen, bis die Tests bestanden sind. Ziel ist es, Fehler zu erkennen, die um eine Größenordnung größer sind als die Toleranzen. Vielleicht wäre es sinnvoll, den rtol -Teil zu lockern , wie isclose oft indirekt von Dingen wie assert_allclose oder verschiedenen Testhelfern von Drittanbietern aufgerufen wird.

Ich habe auf StackOverflow nach Importen im Stil von __future__ gefragt: https://stackoverflow.com/questions/29905278/using-future-style-imports-for-module-specific-features-in-python

TLDR: Es ist möglich, aber nicht einfach oder sauber.

Die Stapel-Introspektion dient nicht nur diesem Zweck, sondern wird als allgemeine Richtlinie zum Ändern der Rückgabewerte von Funktionen vorgeschlagen. Die Frage ist: Sollte dies grundsätzlich geändert werden? Ich denke, wenn die Antwort ja lautet, muss die Abschreibungsdauer angesichts der weit verbreiteten Verwendung mindestens einige Jahre betragen. Python hat nie ein früheres Modul aufgenommen, aber dies ist eine Option, um bei Bedarf zu versuchen, die API-Stabilität zu verbessern.

Die andere Methode wäre, dies einfach als Option isclose(...,symmetric=True) oder assert_allclose(symmetric=True) hinzuzufügen, wobei der Standardwert False , die aktuelle Situation.

Ich bin damit einverstanden, dass dies ein kleines Problem ist, wenn Sie den Werten rtol und atol keine Bedeutung geben, sondern sie nur so einstellen, dass sie Unit-Tests bestehen, wie von @njsmith erwähnt.

Manchmal möchten Sie jedoch sagen, dass der Fehler beispielsweise innerhalb von 1% liegt ( rtol=0.01 ).
In diesem Fall beträgt der Worst-Case-Fehler in Bezug rtol Messung von rtol * abs(b) nähert sich atol , dann atol + rtol * abs(b) ~= 2 * rtol * abs(b) ).

Dies bedeutet, dass einige Werte mit einem Fehler von ~ 2% übergeben werden können:

atol = 1e-8 #default
rtol = 0.01 # 1%

b = 1e-6
a = 1.0199e-6 # ~ 2% larger comapared to b
abs(a - b) <= (atol + rtol * abs(b))
True

Die Implementierung der Idee von @charris würde diesen speziellen Fall geringfügig verschlechtern, da der Vergleich dadurch noch mehr gelockert wird, sich aber dennoch lohnt, da das Symmetrieproblem beseitigt wird und tatsächlich abwärtskompatibel ist.

IMO wäre es besser, wenn Numpy die Math-Funktion verwenden würde, aber ich verstehe, dass die Änderung möglicherweise zu störend und für die meisten Benutzer möglicherweise nicht wichtig ist. Es wäre nützlich, die Option zum Wechseln zwischen dem isclose -Kern zu wählen.

@njsmith : Danke, dass du mich

Ein bisschen Geschichte: Als ich vorgeschlagen habe, die stdlib zu schließen, haben wir numpy sicherlich als Stand der Technik angesehen. Wenn es nur ich wäre, hätte ich möglicherweise einen kompatiblen Ansatz verwendet, um die Kompatibilität zu gewährleisten :-).

Aber der Rest der Community dachte, es sei wichtiger, das zu tun, was für Python "richtig" war, und so folgte eine lange Diskussion ... Ich habe versucht, den größten Teil des PEP-Punktes zu erfassen, wenn Sie nachsehen möchten.

Hier ist der Verweis auf numpy:

https://www.python.org/dev/peps/pep-0485/#numpy -isclose

Sie können sehen, dass die gleichen Punkte wie in dieser Diskussion gemacht wurden.

Am Ende kamen drei wichtige Punkte heraus:

1) Ein symmetrischer Ansatz würde die geringste Überraschung zur Folge haben.

2) Die absolute Standardtoleranz sollte wahrscheinlich Null sein, um keine Annahmen über die Größenordnung der Argumente zu treffen.

3) Der Unterschied zwischen den "schwachen" und "starken" Tests war irrelevant, wenn er mit kleinen Toleranzen verwendet wurde, wie dies der erwartete Anwendungsfall ist.

Am Ende haben wir die "beste" Lösung für math.isclose gefunden.

Aber ist es "besser" genug, um die Abwärtskompatibilität zu brechen? Das glaube ich nicht.

Leider wurden vielen Numpy (und Python) viele Funktionen hinzugefügt, weil sie nützlich waren, aber ohne viel aktuelle Diskussion werden diese Dinge, so dass wir viele suboptimale Designs haben. Dies wird für eine junge Bibliothek erwartet (und ist notwendig), und wir müssen jetzt nur damit leben.

@njsmith ist richtig - Ich denke, nur sehr wenige Anwendungen von np.isclose () haben die Toleranzen, die durch eine strenge FP-Fehleranalyse festgelegt wurden, sondern versuchen einen Fehler mit np.isclose () selbst.

Ich denke jedoch, dass das größere Problem die Standardeinstellung atol - es wird davon ausgegangen, dass Ihre Argumente in der Größenordnung 1 liegen - was eine SEHR falsche Annahme sein könnte und da dies häufig dazu führen würde, dass Tests bestanden werden, sollte dies nicht der Fall sein Benutzer bemerken es möglicherweise nicht.

In [85]: np.isclose(9.0e-9, 1.0e-9)
Out[85]: True

Autsch!

und ja, es sind die atol die dies verursachen:

In [86]: np.isclose(9.0e-9, 1.0e-9, atol=0.0)
Out[86]: False

Es ist also wahrscheinlich eine gute Idee, einen Weg nach vorne zu finden.

Ich mag die Idee mit dem Schlüsselwortargument - scheint viel einfacher zu sein, als mit __future__ und dergleichen zu spielen.

Und wir könnten dann entscheiden, ob wir mit der Ausgabe von Verfallswarnungen beginnen und letztendlich die Standardversion vieler nachgelagerter Versionen ändern möchten ...

Ich möchte den Vorschlag von @bashtage vorschlagen:

"" "
Die andere Methode wäre, dies einfach als Option isclose (..., symmetric = True) oder assert_allclose (symmetric = True) hinzuzufügen, wobei der Standardwert False ist, die aktuelle Situation.
"" "

Ich denke, es ist eine bessere Option als ein neuer Funktionsname und könnte den Weg zu einer zukünftigen Ablehnung und Änderung der Standardeinstellung weisen (oder nicht).

Ich denke, zusätzlich zum (starken) symmetrischen Test sollte atol standardmäßig Null sein.

Angesichts dessen brauchen wir vielleicht einen besseren Namen für den Parameter als symmetric , obwohl es nicht schlecht ist ...

Oh - und es könnte gut sein, darauf zu achten, dass isclose() nicht zusätzlich zu assert allclose() anderer Stelle in numpy aufgerufen wird.

Der einfachste Weg, dies zu tun, besteht wahrscheinlich darin, eine Abwertungswarnung in und einzufügen
Entfernen Sie es dann vor dem Zusammenführen. Wir könnten einfach weitermachen und das setzen
Die darin enthaltene Verfallswarnung besagt, dass vorhandener Code in geändert werden soll
symmetrisch = falsch; Es gibt keinen Grund zu sagen, dass der Standard sein muss
jederzeit geändert, auch wenn die Warnung vorhanden ist.

Müssen wir es auch zu assert_allclose hinzufügen, oder nehmen wir die Änderung nur stillschweigend vor? Es ist nicht wirklich anders, wenn Leute jeden ihrer Tests aktualisieren, um eine Warnung zum Schweigen zu bringen, als wenn sie ihre Tests aktualisieren, um die Toleranzreduzierung zu beheben

@xoviat @ eric-wieser es kann keine rückwärts inkompatiblen Änderungen an assert_allclose oder eine Abwertungswarnung geben, viel zu störend. Es sei denn, ich vermisse, wo Sie eine Abwertungswarnung platzieren möchten?

Ich befürchte, dass dies für infinitesimal immer noch nach viel Schmerz klingt
Gewinn für mich.

Es ist kein Zufall, dass atol standardmäßig ungleich Null ist. Es ist nötig, um zu bekommen
Sinnvolles Standardverhalten für jeden Test, bei dem das erwartete Ergebnis enthalten ist
genaue Nullen.

Es sind keine Änderungen an assert_allclose erforderlich, da diese aktualisiert würden
intern, um das alte Verhalten zu verwenden.

IMO stille Änderungen sind böse! Die Abwertungswarnung ist nur so
Leute müssen schließlich nicht die Flagge in einer interaktiven Eingabeaufforderung eingeben
bekomme das neue Verhalten, nichts weiter

IMO stille Änderungen sind böse!

Einverstanden. Es sollten jedoch keine Änderungen vorgenommen werden. Verfallswarnungen in weit verbreiteten Funktionen zwingen Benutzer (zumindest diejenigen, die tatsächlich Wartungsarbeiten durchführen), Änderungen vorzunehmen.

Was ist mit der Behebung des Nicht-Symmetrie-Problems, wie es @charris vorgeschlagen hat? Dies würde auch etwas Dokumentationsspeicherplatz freigeben, der mit einer Warnung über die schlechten Dinge gefüllt werden könnte, die passieren können, wenn atol != 0.0 .

Wir können dieses Problem nicht beheben, ohne die Leute über die Änderungen zu informieren
Verhalten. Ich kann das nur mit einer Warnung.

Was wirklich schön wäre, ist ein automatisiertes Refactoring-Tool zum Einfügen von Flags
in alten Code. Dann würde 'Wartung' nur ein Skript auf Ihrem ausführen
Code; 5 Minuten Arbeit.

Entschuldigung, dies kann behoben werden, nur mit einer neuen Flagge.

Was ist mit der Behebung des Nicht-Symmetrie-Problems, wie es @charris vorgeschlagen hat?

Dieser Vorschlag (https://github.com/numpy/numpy/issues/10161#issuecomment-349384830) scheint machbar.

Wir können dieses Problem nicht beheben, ohne die Leute über das geänderte Verhalten zu informieren.

Wir reparieren es nicht. Hier geht es um Kosten / Nutzen von Änderungen, die gerade in der Frage der semantischen Versionierung behandelt werden. Dies ist definitiv ein Fall, in dem wir keine Änderungen vornehmen oder Warnungen von einer weit verbreiteten Testfunktion ausgeben. Beachten Sie, dass das aktuelle Verhalten kein Fehler ist (obwohl dies möglicherweise eine suboptimale Wahl ist).

Um klar zu sein, habe ich eine Änderung in isclose vorgeschlagen, aber nicht assert_allclose.
Wenn man sich die Quellen ansieht, wird diese Änderung ein Drittel so störend sein.
Der Nutzen ist jedoch wahrscheinlich immer noch zu gering. Ich glaube niemandem
Einwände gegen das Hinzufügen einer Flagge, richtig?

Ich glaube nicht, dass jemand etwas dagegen hat, eine Flagge hinzuzufügen, richtig?

Nicht sicher, hängt von den Details ab. Für den Vorschlag von

In [1]: import math

In [2]: math.isclose(0, 1e-200)
Out[2]: False

Ich bin dagegen, Flags ohne konkrete Motivationen und Anwendungsfälle hinzuzufügen. Nützlicher Lackmustest: Wenn ein Anfänger Sie fragen würde, warum diese Flagge existiert, wie würden Sie das erklären?

wie würdest du das erklären

  1. Sie verwenden das Flag symmetric=True wenn Sie Anrufe an math.isclose vektorisieren möchten
  2. Es musste eine Flagge sein, damit wir den vorhandenen Code nicht beschädigten.

Ich suche eher nach Situationen, in denen tatsächlich ein Problem gelöst wird.

Wahrscheinlich ist das einzige Problem, das hier gelöst wird, Anfänger zu machen
Denken Sie mehr über die Gleitkomma-Genauigkeit nach. Ich meine, das Beispiel von @rgommers
scheint, als wäre es falsch, aber was ist, wenn Sie mit wirklich kleinen zu tun haben
Zahlen? IMO ist die Implementierung von math.isclose besser, aber ich nicht einmal
Ich denke, darüber besteht Konsens. Leider gibt es nicht wirklich eine
One-Size-Fits-All-Lösung, um festzustellen, ob Zahlen "nahe" sind. Aber
basierend auf den Antworten von anderen (die nicht falsch sind!), weiß ich nicht wirklich
Alle Änderungen an der API, die vorwärts gehen. Ich denke, die einzige Maßnahme ist
wahrscheinlich ein Dokumentationsupdate dann (berühmte letzte Worte, vorausgesetzt ich
vorher gedacht, eine Flagge wäre okay)?

Sicherlich wäre eine Notiz, die mit math.isclose verglichen wird und dokumentiert, wie man ein vektorisiertes Verhalten erhält, das identisch ist, indem man rtol und atol setzt, wenn man möchte, wenn man möchte.

Wenn ich das richtig verstehe, schlug @charris eine Lösung vor, um dies zuzulassen
isclose ist weniger tolerant als es derzeit ist, was nicht brechen würde
irgendwelche Tests. Ich denke immer noch , es wäre eine gute Idee, um eine Warnung zu emittieren (die
Warnung sollte einmal ausgegeben werden), wenn es eine Situation gibt, in der isclose würde
Betrachten Sie Zahlen als "nah", als sie vorher nicht waren. Das ist vielbesser als einfach das Funktionsverhalten still zu ändern und nicht zu lassen
Jeder weiß davon, wenn es sie betrifft.

Ich denke, hier ist eine Klarstellung erforderlich, worüber wir diskutieren. Es gibt zwei Dinge, die math.isclose unterscheiden:

  • Ein anderer Standard für atol
  • Eine andere Definition von rtol

Ich glaube nicht, dass wir etwas gegen das erste Problem unternehmen können, außer es als anders als `math.isclose zu dokumentieren.

Das zweite Problem lässt sich meiner Meinung nach am besten beheben, indem ein symmetric -Argument hinzugefügt wird, das standardmäßig False . Jetzt können wir in unsere Dokumente schreiben _ " np.isclose(x, y, symmetric=True, atol=0) ist eine vektorisierte Version von math.isclose(x, y) " _, die für mich das zu sein scheint, was wir zu lösen versuchen.

Von hier aus haben wir drei Möglichkeiten:

  1. Dokumentieren Sie das zusätzliche Argument und tun Sie nichts anderes
  2. Verwerfen Sie es, isclose ohne das Argument aufzurufen, und zwingen Sie Benutzer, isclose(..., symmetric=False) zu schreiben, um das alte Verhalten ohne Warnung zu erhalten (und ähnliches für allclose ). Ich vermute, dass dies nicht zu viel Code trifft, aber das Ergebnis ist weniger lesbar, ohne großen Gewinn. assert_close würde geändert, um isclose(..., symmetric=False) intern aufzurufen, sodass Benutzer davon nicht betroffen wären
  3. Wie oben, erfordert aber auch das Argument symmetric für assert_close . Dies wäre eine massive Abwanderung stromabwärts
  4. Ändern Sie still das Verhalten

Von diesen halte ich Option 1 für nicht zu beanstanden, aber der Rest klingt nicht nach Dingen, die die Störung wert sind.

Bearbeiten: 2 ist möglicherweise akzeptabel, wenn die Warnung nur ausgegeben wird, wenn sich das Verhalten ändert, was viel weniger laut wäre.

@ eric-wieser Es gibt einen dritten Unterschied: die Art und Weise, wie atol und rtol kombiniert werden. ( math.isclose verwendet max , numpy.isclose verwendet + ). Dies bedeutet, dass es keine allgemeine Möglichkeit gibt, einen math.isclose -Anruf mit einem numpy.isclose -Anruf in Einklang zu bringen, es sei denn, atol oder rtol ist Null.

Ich denke immer noch nicht, dass es sich lohnt, für Benutzer sichtbare APIs hinzuzufügen.

Ich war für Option zwei. Ich bin immer noch für diese Option, mit
die zusätzliche Bestimmung, dass numpy eine automatisierte liefern würde
Refactoring-Tool (zu entry_points hinzugefügt), das Sie einfach auf Ihrem Computer ausführen können
bestehende Projekte, um sie zu beheben. Basierend auf dem, was andere gesagt haben, klingt es so
Diese Option würde von anderen nicht bevorzugt.

Ich bin es nicht und habe mich nie für die Optionen drei oder vier ausgesprochen. Im
Außerdem bin ich nicht dafür, das Funktionsverhalten bis zu einer Warnung zu ändern
wurde für mindestens vier Hauptversionen veröffentlicht.

Unter der Annahme, dass andere mit Option zwei (die sie haben) nicht einverstanden sind, wäre ich es
zugunsten von Option eins. Aber andere (insbesondere @njsmith) sind nicht dafür
einer der Optionen, die Sie hier gegeben haben. Zumindest ist das meine Wahrnehmung.

@njsmith Das ist nicht richtig; Sie können das Funktionsverhalten mit dem Flag ändern.

Ich falte diesen dritten Unterschied in eine Handwelle _ "rtol ist anders" _

"" "
Ich suche eher nach Situationen, in denen tatsächlich ein Problem gelöst wird.
"" "
Ich wette Dollar auf Donuts (was ich tun werde, weil ich keine Ahnung habe, was das bedeutet ...), dass es Tests gibt, die bestehen, die nicht bestehen sollten, weil atol den Test weitaus weniger empfindlich macht ist sollte sein.

Es scheint, dass es drei "Probleme" mit der aktuellen Implementierung gibt:

1) es ist nicht symmetrisch

  • Ich denke, das ist schade, aber wirklich keine große Sache, und es macht fast keinen Unterschied, wenn die Werte wirklich nahe beieinander liegen :-) Ich denke, es macht buchstäblich keinen Unterschied, ob rtol <1e-8 ist (zumindest wenn atol 0,0 ist).

2) Atol beeinflusst das Ergebnis auch dann, wenn es nicht mit Null verglichen wird (das ist unvermeidlich) - aber es ändert die Toleranz effektiv um etwa den Faktor zwei - oder sogar mehr, wenn Atol groß ist, was es sein kann, wenn mit einer großen Ordnung von gearbeitet wird Größenwerte.

3) atol ist ungleich Null - ich denke tatsächlich, dass dies das größte Problem ist (insbesondere mit dem aktuellen Algorithmus zum Hinzufügen beider), da es sehr leicht dazu führen kann, dass Tests bestanden werden, die nicht bestanden werden sollten - und allzu oft sind wir es ein bisschen faul - wir schreiben den Test mit der Standardtoleranz und wenn er erfolgreich ist, denken wir, dass wir fertig sind. (Als ich merkte, dass es so funktionierte, ging ich zurück zu y Code und fand ein paar davon - whoops!

Jemand in diesem Thread sagte etwas über "es würde etwas wringen, wenn:

isclose (1e-200, 0,0)

Standardmäßig wird False zurückgegeben. Ich bin anderer Meinung - ja, das wäre überraschend, aber es würde den Benutzer dazu zwingen, darüber nachzudenken, was los ist, während die aktuelle Implementierung (zum Beispiel) zu folgenden Ergebnissen führt:

In [8]: np.isclose (1e-20, 1e-10)
Out [8]: Richtig

Ja wirklich? einer ist zehn Bestellungen von MAGNITUDE größer als der andere und es kommt zurück True ????

Mein Punkt ist, dass Atol ungleich Null im allgemeinen Fall des Vergleichs mit Null vielleicht weniger überraschende Ergebnisse liefert, aber VIEL gefährlichere und falschere Ergebnisse, wenn mit kleinen Zahlen gearbeitet wird (klein ist wirklich etwas weniger als die Größenordnung 1).

Und wenn Sie mit großen Zahlen arbeiten, beispielsweise größer als 1e8, ist das Standardatol ebenfalls unangemessen.

In Verbindung mit (2) bedeutet dies, dass das Standardatol auch die relativen Toleranztests auf überraschende Weise durcheinander bringen kann.

Also: Nein, es ist kein Fehler und es ist nicht "kaputt", aber es ist ziemlich suboptimal, also wäre es schön, einen Weg vorwärts zu einer besseren Implementierung zu haben.

Ich mochte den Flag-Ansatz, aber ich glaube, ich ändere meine Meinung - das Problem ist, dass, wenn wir ihn nicht ablehnen und das Standard-Flag irgendwann ändern, fast jeder den "alten" Algorithmus verwendet so ziemlich für immer. Und es gab viele gute Argumente, warum wir es wahrscheinlich nicht ablehnen konnten.

Vielleicht ist eine neue Funktion mit einem neuen Namen angebracht. Wir könnten zu den Dokumenten hinzufügen, die die Leute ermutigen, das neue zu verwenden, und möglicherweise Warnungen hinzufügen, wenn Leute das neue verwenden, aber wir würden niemals den Code von irgendjemandem brechen.

Jeder hat eine Idee für einen guten Namen für eine neue Funktion ????

Vielleicht np.math.isclose und Freunde? Ich weiß es nicht.

Das löst, dass np.remainder auch anders ist, und ermöglicht es Ihnen auch, Code mithilfe von from numpy import math einfach zu vektorisieren

Ich wäre also +1 auf einem np.math Modul

Die Einführung neuer Funktionen mit nur geringfügig anderem Verhalten als andere Funktionen, die seit einem Jahrzehnt so funktionieren, ist im Allgemeinen eine sehr schlechte Idee. In diesem Fall gibt es wirklich kein großes Problem, das mit der Dokumentation nicht angemessen gelöst werden kann. Also -1 auf eine neue Funktion. Und definitiv -1 auf einem ganz neuen Submodul.

Ja wirklich? einer ist zehn Bestellungen von MAGNITUDE größer als der andere und es kommt zurück True ????

Ob Ihre Erwartung wahr oder falsch ist, hängt vollständig vom Kontext ab. Wenn dies für Zahlen gilt, die aus einer kontinuierlichen Verteilung auf [0, 1) stammen, dann erwarten Sie wahrscheinlich True. Ein Benutzer sollte wirklich die absoluten / relativen Toleranzen verstehen und wissen, was eine Funktion tatsächlich tut, und dafür sind Dokumente gedacht.

symmetric_isclose() ist ein bisschen langatmig, aber für meine Augen nicht anstößig.: bikeshed: emoji>

Am 10. Dezember 2017, um 20:09 Uhr, schrieb Ralf Gommers [email protected] :

Einführung neuer Funktionen mit nur geringfügig anderem Verhalten als andere
Funktionen, die seit einem Jahrzehnt so funktionieren, sind im Allgemeinen sehr schlecht
Idee.

Ich mag es auch nicht - aber es ist schlimmer, den Code der Leute mit einer Änderung zu brechen.
Haben Sie eine andere Idee als einfach, Numpy nicht besser zu machen?

In diesem Fall gibt es wirklich kein großes Problem, das nicht angemessen sein kann
mit Dokumentation gelöst.

Ich bin anderer Meinung - Standardeinstellungen sind wichtig - sehr.

Und ich glaube nicht, dass es eine Möglichkeit gibt, die Parameter anzupassen, um Ihnen eine zu geben
symmetrischer Vergleich.

Und definitiv -1 auf einem ganz neuen Submodul.

Ich auch. Wenn es andere Dinge im Mathematikmodul ohne Numpy gibt
Äquivalente, die nützlich wären, könnten dem Namespace von numpy hinzugefügt werden
wie alles andere.

Ja wirklich? einer ist zehn Bestellungen von MAGNITUDE größer als der andere und es kommt zurück
Wahr????

Ob Ihre Erwartung wahr oder falsch ist, hängt vollständig vom Kontext ab.

Genau - deshalb gibt es für atol KEINEN "vernünftigen" Standard.

Wenn das für Zahlen ist, die aus einer kontinuierlichen Verteilung auf [0, 1) stammen
dann ja, du wirst wahrscheinlich True erwarten.

Aber isclose wird als relativer Vergleich beworben - und hier die
Relativität wird völlig ausgewaschen, sei der absolute Vergleich,
ohne dass der Benutzer darüber nachgedacht haben muss.

Das ist mein ganzer Punkt - die Standardeinstellung ist NUR angemessen, wenn Sie Ihre erwarten
Werte in der Größenordnung 1. Ein häufiger Fall, sicher, aber nicht
Universal.

Darauf kommt es an, was schlimmer ist - ein falsches Negativ oder ein falsches Positiv.
Und im allgemeinen Anwendungsfall des Testens ist ein falsches Positiv viel schlimmer.

(dh ein Test, der nicht bestanden werden sollte)

Ein Benutzer sollte wirklich absolute / relative Toleranzen verstehen und was a
Funktion tut tatsächlich,

Absolut - aber eine Funktion sollte auch vernünftige Standardeinstellungen haben und a
robuster Algorithmus, der leicht zu verstehen ist.

Ich tendiere dazu, die Dokumentation zu verbessern und die Funktion in Ruhe zu lassen. Das Fehlen von Symmetrie kann erklärt werden als "isclose (a, b) bedeutet, dass a nahe an b liegt, aber aufgrund der variierenden absoluten Genauigkeit des Gleitkommas ist es nicht immer der Fall, dass b nahe an a liegt. b sollte das erwartete Ergebnis sein und a sollte das tatsächliche Ergebnis sein. " Beachten Sie, dass dies zum Testen sinnvoll ist. Der Fall der symmetrischen Funktion ist tatsächlich etwas komplizierter zu rechtfertigen. Der relative Fehler, der eine Teilung beinhaltet, ist nicht symmetrisch.

Ich mag es auch nicht - aber es ist schlimmer, den Code der Leute mit einer Änderung zu brechen. Haben Sie eine andere Idee als einfach, Numpy nicht besser zu machen?

Sie geben hier bereits ein Werturteil ab, dass das Hinzufügen Ihrer neuen Funktion besser ist als keine neue Funktion. Es ist nicht imho. Drei Optionen:

  1. Eine bahnbrechende Änderung - nicht akzeptabel, Sie können aufhören, darüber zu diskutieren.
  2. Einfach bessere Dokumente hinzufügen
  3. Hinzufügen einer Funktion

2 ist insgesamt eine bessere Wahl als 3, daher macht das numpy "besser". Sie ignorieren auch, dass dieses atol / rtol-Ding nicht auf eine einzelne Funktion beschränkt ist. Was kommt als nächstes - ein neues und etwas "besseres" assert_allclose ? Dies macht den Fall für Nur-Dokumente noch deutlicher.

Dies ist ein ziemlich schwerwiegender Fehler. Im Grunde ist der Code, der Ihren Code testet, fehlerhaft ... nicht gut. Würden Sie etwas an den Mond senden, das mit numpy.isclose und default atol getestet wurde? Ich würde es mir zweimal überlegen ... und deshalb müssen wir diese Fallstricke in der Dokumentation hervorheben.
Durch Hinzufügen einer Alias-Funktion wird die Codebasis nur unübersichtlich, es sei denn, sie wird den Benutzern aufgezwungen (dies geschieht nicht).

Ich bin damit einverstanden, dass das Symmetrie-Zeug geringfügig ist, aber wir sollten es trotzdem beheben. Wenn Sie es verlassen, werden Benutzer möglicherweise von echten Fallstricken abgelenkt.

@rgommers schrieb:
"" "
Sie geben hier bereits ein Werturteil ab, dass das Hinzufügen Ihrer neuen Funktion besser ist als keine neue Funktion. Es ist nicht imho.
"" "
Nun, ich habe viel Zeit damit verbracht, über math.isclose nachzudenken und darüber zu debattieren, und wir haben uns zunächst unter anderem die numpy-Implementierung angesehen. Also, ja, ich denke, dieser Ansatz ist besser. Und ich dachte aus dieser Diskussion, dass das so ziemlich ein Konsens war.

Und einen besseren Algorithmus / eine bessere Schnittstelle in numpy zu bekommen, macht es besser, ja.

Vielleicht meinen Sie, dass es NICHT besser ist, sowohl die alte als auch die neue, bessere Funktion in Numpy zu haben, als einfach die alte (vielleicht besser dokumentierte) Funktion dort zu lassen. Sicher, das ist ein absolut gültiger Punkt, aber ich habe versucht, diese Diskussion zu führen, und der vorherige Kommentar, dass "die Einführung neuer Funktionen mit nur geringfügig anderem Verhalten als andere Funktionen, die seit einem Jahrzehnt so funktionieren, im Allgemeinen eine sehr schlechte Idee ist" schien die Diskussion zu beenden - mein Punkt ist, dass wenn der neue Weg "besser genug" ist, als es sich lohnen würde. Wir sind uns eindeutig nicht einig, ob diese spezielle Option "besser genug" ist und nicht, ob sie "besser" ist.

Übrigens habe ich mich persönlich nicht davon überzeugt, dass es eine Änderung wert ist, aber ich möchte die Diskussion führen.

Der Schlüssel hier sind ein paar Annahmen von meiner Seite. Ich weiß nicht, dass wir jemals sicher wissen können, ob sie korrekt sind, aber:

1) np.isclose () wird am häufigsten zum Testen verwendet. Sind Ihre Antworten nah genug an Ihren Erwartungen? - Dies erfolgt über np.assert_all_close oder direkter in Pytest-Tests oder ....

2) Die meisten Menschen führen meistens keine strengen Gleitkomma-Fehleranalysen durch, um festzustellen, wie gut die Antworten voraussichtlich sein werden. Vielmehr versuchen sie einen Wert, und wenn er fehlschlägt, sehen sie sich die Ergebnisse an und entscheiden, ob es sich wirklich um einen Fehler handelt oder ob die Toleranzen des Tests angepasst werden müssen.

  • Dies bedeutet, dass es nicht so wichtig ist, ob atol und rtol zusammengeführt werden und ob der Test symmetrisch ist.

3) Viele Leute beginnen den Prozess in (2) häufig mit Standardtoleranzen und versuchen nur, die Toleranz anzupassen, wenn ein Test fehlschlägt.

  • Dies bedeutet, dass es ziemlich gefährlich ist, ein Standardatol zu haben - Tests zu bestehen, die nicht bestanden werden sollten, ist eine wirklich schlechte Sache.

4) Die Leute lesen keine Dokumente (über die anfängliche Phase "Wie nenne ich das?" Hinaus) - zumindest nicht, bis sie verwirrendes Verhalten feststellen. Dann könnten sie hineingehen und versuchen zu verstehen, wie etwas wirklich funktioniert, um die Verwirrung zu beseitigen . Aber siehe (3) - Wenn ein Test nicht fehlschlägt, wissen sie nicht, ob sie sich die Dokumente ansehen müssen, um zu verstehen, warum.

All dies führt mich zu dem Schluss, dass Numpy mit einem mehr math.isclose-ähnlichen FP-Nähe-Test "besser" wäre.

Und warum besser dokumentiert eine tolle Idee, aber nicht genug.

Vielleicht irre ich mich völlig, und die meisten Leute lesen die Dokumente sorgfältig durch und wählen die meiste Zeit sowohl rtol als auch atol sorgfältig für ihr Problem aus - aber ich weiß, dass ich oder das halbe Dutzend Leute in meinem Team das getan haben, bis ich es wurde sich dieser Probleme bewusst sein.

: bikeshed: (verdammt, das hat nicht funktioniert - kein schickes Emoji)

vielleicht relatively_close oder rel_close ?

Eine zusätzliche "lustige" Falte: assert_allclose verwendet tatsächlich atol = 0 von
Standard. Irgendwo gibt es einen weiteren Thread, in dem darüber diskutiert wird, ob wir das Problem beheben können
diese Inkonsistenz. (Auf meinem Handy kann ich es also nicht leicht finden.)

Am 11. Dezember 2017 um 14:58 Uhr schrieb "Chris Barker" [email protected] :

@rgommers https://github.com/rgommers schrieb:
"" "
Sie geben hier bereits ein Werturteil ab, das Ihre neue Funktion hinzufügt
ist besser als keine neue Funktion. Es ist nicht imho.
"" "
Nun, ich habe viel Zeit damit verbracht, darüber nachzudenken und darüber zu debattieren
math.isclose, und wir haben uns zunächst die numpy-Implementierung angesehen
unter anderen. Also, ja, ich denke, dieser Ansatz ist besser. Und ich dachte
Aus dieser Diskussion ging hervor, dass dies so ziemlich ein Konsens war.

Und einen besseren Algorithmus / eine bessere Schnittstelle in numpy zu bekommen, macht es besser, ja.

Vielleicht meinen Sie damit, dass sowohl das Alte als auch das Neue besser funktionieren
Numpy ist NICHT besser, als einfach das Alte zu verlassen (vielleicht besser
dokumentierte) Funktion dort. Sicher, das ist ein absolut gültiger Punkt, aber ich war es
Ich versuche, diese Diskussion zu führen, und den vorherigen Kommentar, dass "Introducing
neue Funktionen mit nur geringfügig anderem Verhalten als andere Funktionen
das seit einem Jahrzehnt so funktioniert hat, ist im Allgemeinen eine sehr schlechte Idee "
schien die Diskussion zu beenden - mein Punkt ist, wenn der neue Weg ist
"besser genug" als es sich lohnen würde. Was wir eindeutig nicht haben
Konsens darüber, ob diese spezielle Option "besser genug" ist, nicht
ob es "besser" ist.

Übrigens habe ich mich persönlich nicht davon überzeugt, dass es sich lohnt
ändern, aber ich möchte die Diskussion haben.

Der Schlüssel hier sind ein paar Annahmen von meiner Seite. Ich weiß nicht, dass wir können
jemals sicher wissen, ob sie richtig sind, aber:

1.

Die größte Verwendung von np.isclose () ist das Testen - sind Ihre Antworten
nah genug an dem, was Sie erwarten? - Dies erfolgt über np.assert_all_close oder
direkter, in Pytest-Tests oder ....
2.

Die meisten Menschen tun meistens nichts so Rigoroses
Gleitkomma-Fehleranalyse, um festzustellen, wie gut die Antworten sind
erwartet zu sein. Vielmehr versuchen sie einen Wert, und wenn er fehlschlägt, schauen sie sich den an
Ergebnisse und entscheiden, ob es wirklich ein Fehler ist oder ob sie die anpassen müssen
Toleranzen des Tests.

  • das bedeutet, dass es nicht so wichtig ist, ob das atol und
    rtol wird zusammengeführt und ob der Test symmetrisch ist.

  • Viele Leute beginnen den Prozess meistens in (2) mit
    Standardtoleranzen und versuchen Sie nur, die Toleranz anzupassen, wenn ein Test fehlschlägt.

  • Dies bedeutet, dass ein Standardatol ziemlich gefährlich ist - Tests
    Passieren, das sollte nicht wirklich schlecht sein.

  • Die Leute lesen keine Dokumente (über das anfängliche "Wie nenne ich das?"
    Bühne) - zumindest nicht, bis sie verwirrendes Verhalten finden, und dann sie
    könnte hineingehen und versuchen zu verstehen, wie etwas wirklich funktioniert, um aufzuklären
    Die Verwirrung. Aber siehe (3) - wenn ein Test nicht fehlschlägt, wissen sie es nicht
    Schauen Sie sich die Dokumente an, um zu verstehen, warum.

All dies führt mich zu dem Schluss, dass Numpy mit a "besser" wäre
mehr math.isclose-like FP Nähe Test.

Und warum besser dokumentiert eine tolle Idee, aber nicht genug.

Vielleicht irre ich mich total und die meisten Leute lesen die Dokumente sorgfältig durch und
wähle rtol und atol die meiste Zeit sorgfältig für ihr Problem aus -
Aber ich weiß, dass ich und noch ein halbes Dutzend Leute in meinem Team das getan haben, bis ich
wurde auf diese Probleme aufmerksam.

: bikeshed: (verdammt, das hat nicht funktioniert - kein schickes Emoji)

vielleicht relativ geschlossen oder rel geschlossen?

- -
Sie erhalten dies, weil Sie erwähnt wurden.
Antworte direkt auf diese E-Mail und sieh sie dir auf GitHub an
https://github.com/numpy/numpy/issues/10161#issuecomment-350886540 oder stumm schalten
der Faden
https://github.com/notifications/unsubscribe-auth/AAlOaNquy47fsOkvBlxcSa-Mxyhgdimlks5s_bORgaJpZM4Q2J-P
.

Du meinst # 3183?

assert_allclose verwendet standardmäßig atol = 0.

Interessant - dadurch fühle ich mich besser.

Dies bringt eine verschwommene Erinnerung an vergangene Diskussionen über Unterschiede zwischen den beiden zurück - war das die einzige?

Hallo,
Meine Thermo-, Flüssigkeits- und HT-Bibliotheken verwenden in großem Umfang assert_allclose von numpy, daher teile ich hier einige Gedanken, wie sie zusammenhängen. Dieser Thread lässt den Verhaltensunterschied sehr alarmierend erscheinen, und ein wenig wie die Leute sollten erwarten, Fehler in ihrem Code zu finden, weil es an Symmetrie mangelt und / oder wenn Atol und RTOL sowie das Standardatol (das in assert_allclose nicht vorhanden ist) unterschiedlich kombiniert werden , Ich weiß). Also wollte ich sehen, ob meine Bibliotheken Fehler hatten, und habe eine sehr grobe Implementierung von assert_allclose gehackt, die ich dann geändert habe, um sie stattdessen vorübergehend zu verwenden.

Ich denke, meine Verwendung von assert_allclose ist repräsentativ - ich vergleiche individuell ausgewählte Werte und mache Tests, bei denen ich Dinge verwirre und assert_allclose für das Ergebnis von Funktionen parametrisch aufrufe. Ich vergleiche Ints und Floats aller Größenordnungen. Ich habe relativ wenig darüber nachgedacht, ein rtol oder atol zu wählen, nur selten ein atol hinzuzufügen oder rtol zu einem weniger strengen Standard zu ändern. Die Bibliotheken rufen assert_allclose 13159, 1178 bzw. 4243 Mal auf.

Also habe ich die Änderung vorgenommen und meine Testtests durchgeführt. Ich bin sehr glücklich zu sagen, dass ich keine neuen Fehler oder Testfehler gefunden habe . Die einzigen Testfehler, die ich finden konnte, waren meine Implementierung von assert_allclose.

Ich weiß, dass es andere gibt, die weniger Glück haben und auf ein Problem stoßen, wenn etwas in assert_allclose oder isclose geändert wird. Ich persönlich würde mich beim Schreiben von Tests wohler fühlen, wenn ich einen assert_allclose-Modus hätte, der das Verhalten von math.allclose repliziert, sei es durch eine andere Funktion oder ein symmetric -Flag. Aber ich weiß, dass das eine Menge Arbeit für jemanden ist, und es gab noch keine PRs. Ich bin froh, dass ich meinen Code auch nur einmal auf diesen Fehler überprüfen kann!

4880 ist der, an den ich gedacht habe.

Am 11. Dezember 2017, um 17:01 Uhr, notifiziert Nathaniel J. [email protected]
schrieb:

4880 https://github.com/numpy/numpy/pull/4880 ist das, woran ich gedacht habe

von.

Vielen Dank. Beachten Sie, dass das Beispiel für das Statistikmodell meine Aussage zum Thema gut macht
Standardwert von atol - alles andere als 0.0 ist gefährlich.

Zeigt die Tatsache, dass dies alle paar Jahre geschieht, an, dass wir sollten
endlich etwas dagegen tun?

Vielleicht schon. Es ist eine kleine Warze, aber manchmal tragen diese kleinen Belästigungen bei
im Laufe der Zeit.

Und während ich erfreut bin, dass assert_allclose atol standardmäßig auf Null gesetzt hat
(Ich unterstütze meinen Standpunkt, dass dies eine akzeptable Option ist, auch wenn Sie dies nicht tun
Ich bin mir einig, dass dies die beste Option ist. Viele von uns - und immer mehr - sind es nicht
using unittest und kann daher np.all_close direkt in Tests verwenden.

Und ja Ralf, wenn wir etwas ändern, werden wir alle drei ändern wollen
eng verwandte Funktionen :-(. Aber das gibt uns die Chance, sie zu machen
konsequenter, ein Bonus?

Obwohl der py2-3-Übergang nicht sehr gut verlaufen ist, gibt es etwas zu tun
sagte, dass es irgendwann eine "es ist in Ordnung, die Warzen aufzuräumen" -Version gibt :-)

Es gibt noch eine andere Möglichkeit, is_close tatsächlich in die (tatsächlich bessere) mathematische Version von atol=0 : Ändern Sie die Standardeinstellung in None und versuchen Sie es mit atol=0 ;; wenn alle True einfach zurückkehren; Wenn einige False , versuchen Sie es erneut mit Standard atol Wenn sich die Ergebnisse ändern, wird eine Abwertungswarnung ausgegeben (und das "alte" Ergebnis zurückgegeben).

Leider kann man nicht gleichzeitig Symmetrie und Atol ausführen, da sie in verschiedene Richtungen gehen (dh man müsste immer beide Fälle ausführen, was ein bisschen viel zu sein scheint). Aber ich mag den atol Standard nicht viel mehr als den Mangel an Symmetrie ...

Ich bin nicht dafür, irgendwelche Funktionen zu ändern, es sei denn, es gibt eine Funktion, die
Sie können verwenden, dass das alte Verhalten hat. Darüber hinaus sollte es eine geben
automatisiertes Refactoring-Tool, um diese Änderung vorzunehmen, wenn dies durchgeführt wird. Das ist jedoch nicht
sogar jetzt auf dem Tisch.

Der py3k-Übergang ist nicht etwas, das wir jemals wieder haben wollen und es
ist kein Vorbild. Es ist nicht gut, Aufräumarbeiten in einer großen Version zusammenzufassen
nähern Sie sich IMO.

Obwohl der py2-3-Übergang nicht sehr gut verlaufen ist, gibt es etwas zu sagen, wenn man irgendwann die Version „Es ist in Ordnung, die Warzen aufzuräumen“ hat :-)

Nur um zu adressieren diese allgemeine Idee , dass spezielle Versionsnummern Bruch Änderungen OK machen können: Die allgemeine Regel ist , dass es in Ordnung ist , die Warzen zu bereinigen, wenn es ein klaren Plan für den Übergang ist die inakzeptable Schmerz vermeidet und die Vorteile sind ausreichend , um das zu rechtfertigen Kosten. Der entscheidende Punkt hierbei ist, dass das Urteil in Bezug auf die Auswirkungen auf die Benutzer erfolgen muss und nicht darauf, ob wir "die Regeln befolgt" haben. (Wenn Sie ausgefallen sein möchten, sind wir Konsequentialisten und keine Deontologen .) Der einzige Grund, eine bestimmte Version als "Dies ist diejenige, die Dinge kaputt macht" zu deklarieren, besteht darin, den Benutzern die Handhabung wesentlich zu erleichtern. IMO sind die Vorteile des Zusammenführens von Änderungen im Allgemeinen gering, wenn sie überhaupt vorhanden sind - fehlerhafter Code ist fehlerhafter Code - und selbst wenn sie vorhanden sind, ist es sehr selten, dass sie die Kosten-Nutzen-Analyse von "Nein" auf "Nein" tippen. Ja".

atol ist ungleich Null, standardmäßig - ich denke tatsächlich, dass dies das größte Problem ist (insbesondere beim aktuellen Algorithmus zum Hinzufügen beider), da es sehr leicht dazu führen kann, dass Tests bestanden werden, die nicht bestanden werden sollten - und allzu oft sind wir ein bisschen faul - wir schreiben den Test mit der Standardtoleranz und wenn er erfolgreich ist, denken wir, dass wir fertig sind. (Als ich merkte, dass es so funktionierte, ging ich zurück zu y Code und fand ein paar davon - whoops!

Beachten Sie, dass das Beispiel für das Statistikmodell meine Aussage zum Standard von atol deutlich macht - alles andere als 0.0 ist gefährlich. [...] viele von uns - und immer mehr - verwenden nicht unittest und verwenden daher np.all_close möglicherweise direkt in Tests.

"Wir sollten den Benutzercode brechen, um die Konsistenz mit einem anderen Paket zu erhöhen" punktet auf der Kosten-Nutzen-Skala nicht sehr gut. „Es gibt Unstimmigkeiten innerhalb numpy , die nicht nur verwirrend, sondern in einer Art und Weise verwirrend , die direkt führen zu stille Fehler in Benutzercode, und wir beheben können“ ist viel mehr überzeugend. Ich habe mir noch keine Meinung gebildet, aber wenn Sie hier Fortschritte machen wollen, dann ist dies das, was ich vorantreiben würde.

Eine Notiz:

"" Ich habe relativ wenig darüber nachgedacht, ein RTOL oder AtOL zu wählen.
nur selten ein Atol hinzufügen
-snip-

$ call assert_allclose 13159, 1178 bzw. 4243 mal.

-snip-

Ich habe keine neuen Fehler oder Testfehler gefunden .

"" "

Gute Nachrichten, obwohl ich feststelle, dass assert_allclose atol standardmäßig auf Null gesetzt hat. Und
deshalb :-)

@njsmith schrieb:

"Wir sollten den Benutzercode brechen, um die Konsistenz mit einem anderen Paket zu erhöhen."

Ich glaube nicht, dass irgendjemand in diesem Thread das befürwortet - ich bin mir sicher nicht. Die einzige Konsistenz, die jemand befürwortet, ist die Konsistenz zwischen den zugehörigen Numpy-Funktionen.

"Es gibt Inkonsistenzen in numpy, die nicht nur verwirrend sind, sondern auf eine Weise verwirrend, die direkt zu stillen Fehlern im Benutzercode führt, und wir können das beheben."

DAS befürworte ich zumindest. Und ich denke die meisten anderen.

Das Problem ist, dass wir es auch nicht beheben können:

Die Abwärtskompatibilität zu brechen, was meiner Meinung nach niemand für ernst genug hält - selbst bei einem Abschreibungszyklus.

Oder

Erstellen einer neuen Flagge oder Funktion.

Ich denke, eine neue Funktion wäre ein sauberer Weg, dies zu tun. Alter Code könnte so lange unverändert bleiben, wie er möchte, neuer Code könnte die neuen Funktionen verwenden, und ein Suchen und Ersetzen (oder ein paar Importe als Aufrufe) könnte es einfach machen, jeweils eine Datei zu wechseln.

(Ich nehme an, Sie könnten sogar Affen-Patch-Numpy in Ihrem Testcode verwenden ...)

Wir haben schon:

  • allclose
  • assert_allclose
  • assert_almost_equal
  • assert_approx_equal
  • assert_array_almost_equal
  • assert_array_almost_equal_nulp
  • assert_array_max_ulp

Ich denke nicht, dass das Hinzufügen weiterer Optionen zu dieser Liste für echte Benutzer einen großen Unterschied bedeuten wird.

Nun, ich habe viel Zeit damit verbracht, über math.isclose nachzudenken und darüber zu debattieren, und wir haben uns zunächst unter anderem die numpy-Implementierung angesehen. Also, ja, ich denke, dieser Ansatz ist besser.

Ich auch, und ich war einer der Hauptbetreuer von numpy.testing - dies ist kaum ein neues Problem. Wenn Sie mit Großbuchstaben darauf bestehen, dass Sie Recht haben, ist dies nicht der Fall.

Vielleicht meinen Sie, dass es NICHT besser ist, sowohl die alte als auch die neue, bessere Funktion in Numpy zu haben, als einfach die alte (vielleicht besser dokumentierte) Funktion dort zu lassen. Sicher, das ist ein absolut gültiger Punkt, aber ich habe versucht, diese Diskussion nicht zu führen.

In der Tat sollte klar sein, dass ich das gemeint habe.

"Die Einführung neuer Funktionen mit nur geringfügig anderem Verhalten als andere Funktionen, die seit einem Jahrzehnt so funktionieren, ist im Allgemeinen eine sehr schlechte Idee", schien die Diskussion zu beenden

Nein, es weist auf ein echtes Problem beim Hinzufügen neuer Funktionen hin, das zu oft ignoriert oder nicht ausreichend gewichtet wird. In diesem Fall scheint es vielen Kernentwicklern ziemlich klar zu sein - es sieht so aus, als ob Sie das Urteil bekommen, dass dieses Schiff von @njsmith , @pv , @charris und mir

Ich entschuldige mich im Voraus für das Aufwärmen, aber assert_allclose ist das richtige Verhalten (oder zumindest nahe genug daran). isclose kann jedoch Menschen in Schwierigkeiten bringen, da es eine absolute Toleranz voraussetzt, wie andere angemerkt haben. Ich denke darüber nach, eine PR einzureichen, um ein großes rotes Kästchen auf der Dokumentationsseite np.isclose zu platzieren, um die Leute vor diesem Verhalten zu warnen. Wie klingt das?

Ich entschuldige mich im Voraus für das Aufwärmen, aber assert_allclose ist das
korrektes Verhalten (oder zumindest nahe genug daran). Allerdings kann isclose bekommen
Menschen in Schwierigkeiten, weil es eine absolute Toleranz voraussetzt, wie es andere getan haben
notiert. Ich denke darüber nach, eine PR einzureichen, um eine große rote Box auf die zu setzen
np.isclose-Dokumentationsseite, um Personen vor diesem Verhalten zu warnen. Wie geht das?
dieser Klang?

+1

Ich bin mir einig, dass die Dokumente besser sein sollten.

Vielen Dank,

-CHB

- -
Sie erhalten dies, weil Sie erwähnt wurden.
Antworte direkt auf diese E-Mail und sieh sie dir auf GitHub an
https://github.com/numpy/numpy/issues/10161#issuecomment-351182296 oder stumm schalten
der Faden
https://github.com/notifications/unsubscribe-auth/AA38YDw4sdhRWYmeeyr4met1RCwWsjMQks5s_uBmgaJpZM4Q2J-P
.

Ich unterstütze die Verbesserung der Dokumentation, denke aber, dass die vorgeschlagene Änderung nicht so hilfreich ist, wie sie sein könnte.

.. warning :: Die Standardeinstellung atol ist nicht für Zahlen geeignet, die
sind viel weniger als eins.

Erstens ist diese Warnung im Allgemeinen nicht einmal wahr. Der Standardwert atol _ ist geeignet, wenn Sie Zahlen kleiner als 1e-8 gleich Null behandeln möchten. Dies ist mit einer relativen Toleranz nicht möglich, weshalb eine absolute Toleranz besteht. Umgekehrt ist die Standardeinstellung atol _ nicht geeignet, wenn Sie Zahlen kleiner als 1e-8 als sinnvoll behandeln möchten. Nehmen wir nicht an, dass eine Größe für alle passt.

Deshalb, @xoviat ,

... assert_allclose _ist das richtige Verhalten (oder zumindest nahe genug daran).

Ich denke, das Problem mit den aktuellen Dokumenten ist, dass es sehr gut beschreibt, was atol ist, aber nicht beschreibt, warum es dort ist, und daher verstehen Benutzer möglicherweise nicht, wann sie den Standardwert ändern müssen .

Ich schlage etwas vor wie:

"Wenn Sie einen kleinen Wert ungleich Null von atol festlegen, können Sie Zahlen, die sehr nahe bei Null liegen, als effektiv gleich Null behandeln. Daher ist der Standardwert von atol möglicherweise nicht für Ihre Verwendung geeignet Wählen Sie atol so, dass Zahlen, die größer als atol sind, von Ihnen als aussagekräftig (von Null verschieden) und Zahlen, die kleiner als atol sind, von Ihnen als vernachlässigbar angesehen werden (wie Null). "

Zuletzt würde ich den Docstrings von isclose und allclose dieselbe Notiz hinzufügen.

Das ist mein Vorschlag. Nimm es oder lass es.
Prost.

Bitte hinterlassen Sie ein Feedback zur PR. Insbesondere ist Ihr Vorschlag IMO zu ausführlich.

Tut mir leid, wenn ich zu nervig war - ich habe wirklich noch nicht gedacht, dass es einen Konsens gibt.

@xoviat : Danke, dass hast .

Da dies wieder auftauchen wird, werde ich (wahrscheinlich) diese Diskussion mit einer Mini-Version eines NEP beenden, die abgelehnt werden soll - fassen Sie die Vorschläge und die Gründe für die Ablehnung zusammen. Für die Aufzeichnung - da die vorherigen Ausgaben einfach irgendwie verblasst sind.

Es tut mir leid, dass Sie das Problem mit py2 / 3 angesprochen haben. Ob / wie Warzen in Numpy aufgeräumt werden, ist eine Diskussion für einen anderen Ort und eine andere Zeit.

Das Problem mit isclose()

Dieses Problem (und andere, auf die verwiesen wird) ist das Ergebnis von Beobachtungen, dass numpy.isclose() und Freunde einen weniger als optimalen Algorithmus verwenden, einen umstrittenen Standard für atol haben und die verschiedenen verwandten Funktionen unterschiedliche Standardeinstellungen haben. Dies führt insgesamt zu Verwirrung bei den Benutzern und im schlimmsten Fall zu falsch positiven Tests, wenn Benutzer nicht über das Festlegen des Werts atol nachdenken.

Insbesondere die Implementierung in der stdlib: math.isclose() bietet einen anderen und wohl besseren Algorithmus und Standardeinstellungen: Es handelt sich um einen symmetrischen Test, es werden weder rtol noch atol gemischt, und das Standardatol ist 0.0

Es besteht nahezu Konsens darüber, dass die Situation nicht ideal ist, aber kein Konsens darüber, dass es schlimm genug ist, etwas dagegen zu unternehmen.

Berücksichtigte Optionen:

Ändern der Algorithmen und / oder Standardeinstellungen:

Universell abgelehnt aufgrund von Abwärtskompatibilitätsproblemen, selbst mit einem Verfallszeitraum und Warnungen - diese Funktionen werden häufig in Tests verwendet, sodass dies zumindest ein großer Ärger wäre.

Hinzufügen eines zusätzlichen Parameters mit einem Flag zur Auswahl eines anderen Algorithmus

Dies würde keinen vorhandenen Code beschädigen, sondern mit einer hässlichen und verwirrenden API für immer bestehen bleiben.

Hinzufügen einer Direktive vom Typ __future__

TLDR: Es ist möglich, aber nicht einfach oder sauber. Niemand schien dies verfolgen zu wollen.

Eine weitere Funktion erstellen

Dies schien die einzige Option zu sein, die Anklang fand, wurde jedoch von den Kernentwicklern, die an der Diskussion teilnahmen, nicht unterstützt.

Der sauberste Weg, dies zu "beheben", wäre das Hinzufügen eines np.rel_close() [oder eines anderen Namens] mit einem neuen Algorithmus und Standardwerten, wahrscheinlich denjenigen, die in math.isclose . Die neue Funktion wird als "empfohlene" Funktion für zukünftigen Code dokumentiert. Es wäre möglich, in Zukunft Abwertungswarnungen zu den alten hinzuzufügen - aber niemand schien zu glauben, dass sich der Lärm zu diesem Zeitpunkt lohnen würde.

Ein Refactoring-Tool könnte gebaut werden, um den Ersatz herzustellen - aber wer wird das für diese eine Verwendung tun?

Dies würde auf absehbare Zeit wahrscheinlich zu zwei sehr ähnlichen Funktionen führen. "Die Einführung neuer Funktionen mit nur geringfügig anderem Verhalten als andere Funktionen, die seit einem Jahrzehnt so funktionieren, ist im Allgemeinen eine sehr schlechte Idee."

Fazit:

Es lohnt sich nicht für den kleinen Gewinn, aber bessere Dokumente sind in Ordnung, und das wird hier gemacht: # 10214

Ich habe noch eine Frage:

@njsmith schrieb:

"" "
Wir haben schon:

allclose
assert_allclose
assert_almost_equal
assert_approx_equal
assert_array_almost_equal
assert_array_almost_equal_nulp
assert_array_max_ulp

Ich denke nicht, dass das Hinzufügen weiterer Optionen zu dieser Liste für echte Benutzer einen großen Unterschied bedeuten wird.
"" "

Meinst du, dass das Hinzufügen eines neuen eine gute Idee wäre?

Ich würde auch bemerken:

Die meisten davon sind Behauptungen - und die Verbreitung von Behauptungen ist ein Nebeneffekt der unittesten Architektur.

Da viele von uns zu anderen Testarchitekturen (z. B. Pytest) wechseln, entfällt die Notwendigkeit von Asserts.

Was also mit numpy.testing zu tun ist, ist eine andere Frage als was mit numpy core zu tun ist.

Da viele von uns zu anderen Testarchitekturen (z. B. Pytest) wechseln, entfällt die Notwendigkeit von Asserts.

Eigentlich ist das eine Gefahr für sich. Tests können von assert_allclose(...) in assert np.allclose(...) geändert werden und werden stillschweigend weniger streng, was eine schlechte Sache ist.

Ich verwende immer noch assert_allclose in der Pytest-Umgebung, da es eine hilfreiche Fehlermeldung gibt:

    def test_shs():
        a = [0.1, 0.2, 0.3, 0.4]
        b = [0.2, 0.3, 0.3, 0.4]

>       np.testing.assert_allclose(a,b)
E       AssertionError: 
E       Not equal to tolerance rtol=1e-07, atol=0
E       
E       (mismatch 50.0%)
E        x: array([ 0.1,  0.2,  0.3,  0.4])
E        y: array([ 0.2,  0.3,  0.3,  0.4])

vs mit assert np.allclose()

    def test_shs():
        a = [0.1, 0.2, 0.3, 0.4]
        b = [0.2, 0.3, 0.3, 0.4]
>       assert np.allclose(a, b)
E       assert False
E        +  where False = <function allclose at 0x7f20b13c9840>([0.1, 0.2, 0.3, 0.4], [0.2, 0.3, 0.3, 0.4])
E        +    where <function allclose at 0x7f20b13c9840> = np.allclose

Es könnte möglich sein, dies durch die Implementierung von pytest_assertrepr_compare zu beheben, aber ich bin nicht sicher, wie ich das auf Funktionsaufrufe anwenden soll, und kann nicht herausfinden, wo pytest es überhaupt aufruft.

@ Eric-Wieser: schrieb:

"Eigentlich ist dies eine Gefahr für sich. Tests können von assert_allclose (...) in assert np.allclose (...) geändert werden und werden stillschweigend weniger streng, was eine schlechte Sache ist."

Genau mein Punkt - es ist eine "schlechte Idee" anzunehmen, dass jeder die Asserts zum Testen verwenden wird und sich daher nicht darum kümmern muss, ob die Standardeinstellungen von isclose () und allclose () zum Testen geeignet sind - im Idealfall Welt sollten sie sicherlich sein.

Meinst du, dass das Hinzufügen eines neuen eine gute Idee wäre?

Nein, ich meinte, da wir bereits eine ganze Reihe leicht unterschiedlicher Arten haben, fast gleiche Tests auszudrücken, werden die meisten Benutzer leider noch eine weitere Ergänzung nicht bemerken oder verstehen.

Ich würde auch bemerken:
Die meisten davon sind Behauptungen - und die Verbreitung von Behauptungen ist ein Nebeneffekt der unittesten Architektur.
Da viele von uns zu anderen Testarchitekturen (z. B. Pytest) wechseln, entfällt die Notwendigkeit von Asserts.

Sie werden zufällig als Behauptungen geschrieben, aber AFAICT jede dieser Funktionen codiert tatsächlich eine andere Definition von "fast gleich". (Ich denke. Einige der Unterscheidungen sind so dunkel, dass ich nicht sagen kann, ob sie echt sind oder nicht.)

Ändern der Algorithmen und / oder Standardeinstellungen:
Universell abgelehnt aufgrund von Abwärtskompatibilitätsproblemen, selbst mit einem Verfallszeitraum und Warnungen - diese Funktionen werden häufig in Tests verwendet, sodass dies zumindest ein großer Ärger wäre.

Ich würde ganz legt es nicht so. Für mich ist dies der einzige Ansatz, der möglicherweise einen ausreichenden Nutzen hätte, um die Kosten zu rechtfertigen. Ich sage nicht, dass sie es tun

Wenn jemand auftauchte und sagte: "Ich habe meine vorgeschlagene Änderung bei 3 großen Projekten versucht, und es führte zu 12 zusätzlichen Fehlern aus 10.000 Tests, und von diesen 12 waren 8 tatsächlich stille Fehler, die von den alten versteckt worden waren schlechte Standardeinstellungen "... das wäre ziemlich überzeugend. Zumal dies ein Fall ist, in dem wir die technische Fähigkeit haben, eng gezielte Warnungen auszuführen. Ich vermute, die tatsächlichen Zahlen wären nicht ganz so günstig, aber bis jemand nachschaut, wer weiß.

Am Montag, 18. Dezember 2017, um 15:57 Uhr, Nathaniel J. Smith <
[email protected]> schrieb:

Nein, ich meinte, dass wir bereits eine ganze Menagerie von haben
Leider etwas andere Ausdrucksformen für fast gleiche Tests
Die meisten Benutzer werden noch eine weitere Ergänzung nicht bemerken oder verstehen.

Nun, es gibt einen großen Unterschied - jeder davon wurde hinzugefügt, weil er es tat
etwas anderes , und mit den Launen des Gleitkommas
Unterschiede können wichtig sein.

Eine neue Funktion der relativen Nähe würde im Wesentlichen dasselbe tun, aber
mach es besser". Und das Ziel wäre es, die Verwendung des neuen zu empfehlen
anstelle des alten (und vielleicht das alte irgendwann ablehnen).

Ehrlich gesagt bin ich mir nicht sicher, ob das ein Argument für oder gegen die Idee ist,
obwohl.

Zum Beispiel, wenn jemand auftauchte und sagte: "Ich habe meine vorgeschlagene Änderung auf 3 groß ausprobiert

Projekte, und es führte zu 12 zusätzlichen Fehlern aus 10.000 Tests und von diesen
12, 8 von ihnen waren tatsächlich stille Käfer, die vom alten Bösen versteckt worden waren
Standardeinstellungen "... das wäre ziemlich überzeugend. Zumal dies eine ist
Fall, in dem wir die technische Fähigkeit haben, eng gezielte Warnungen auszuführen.
Ich vermute, die tatsächlichen Zahlen wären nicht ganz so günstig, aber bis
jemand prüft, wer weiß.

hmm, meine Codebasis hat ungefähr 1500 Tests - nicht 10.000, aber ich gebe das a
Schuss. Wenn nichts anderes, kann ich einen Fehler oder einen schlechten Test oder zwei finden. Oder mehr bekommen
Beruhigung!

Hallo zusammen,

Wollte hier einschalten, nachdem ein Kollege auf dieses Problem gestoßen war.

Haftungsausschluss: Ich habe nicht wirklich über die Logik nachgedacht, bevor ich „Feuer in der Halle“ geschrien und über den Zaun geworfen habe. Wenn ich einen peinlichen Hasch daraus gemacht habe, sei bitte nett, bitte.

Für mich klingt das alles sehr nach dem klassischen Architektur- / Design-Problem „Huhn & Ei“ - Semantik vs. Implementierung. Nicht alle Fehler sind im Code vorhanden, manchmal auch innerhalb der Semantik. Dies unterscheidet sich nicht viel (wenn überhaupt) von einem Algorithmus, der fehlerfrei implementiert wird, nur um festzustellen, dass der Algorithmus fehlerhaft ist - der Fehler ist nicht im Code, sondern im Algorithmus, aber so oder so ist er immer noch ein Fehler. Grundsätzlich klingt diese Diskussion ein bisschen wie der klassische Witz "Es ist kein Fehler, es ist eine Funktion". Natürlich ist eine „Wahl“ genau das, aber meiner Meinung nach signalisiert dies normalerweise das Ende der Überlegungen - wenn die Semantik so gewählt wird, wie sie ist, wie sie implementiert ist, dann ist die Implementierung allesamt cool, Ende der Diskussion.

Was ist also die "gewünschte" und / oder "erwartete" Semantik von isclose() ? Wenn ich darüber nachdenke, konvergiere ich unaufhaltsam mit der Semantik, die vom Benutzer definiert wird, dh der Benutzer muss in der Lage sein, die Semantik zu definieren Definition von "schließen".

Standardeinstellungen

In Bezug auf die Standardeinstellungen wird dadurch letztendlich keine Semantik gebrochen. Eine schlechte Wahl ist jedoch gefährlich. Wenn der Standardwert ungleich Null _nur_ gewählt wurde, um ein angemessenes Verhalten für abs(a - b) == 0 erzielen, dann klingt dies definitiv wie die falsche Lösung. Dieser bestimmte Zustand wäre besser geeignet, wenn er speziell in einem speziellen Fall vorliegt, da er semantisch in einem speziellen Fall ist. Es gibt keinen "Wackelraum" in der Definition von "schließen", wenn der Unterschied Null ist, es ist der selbstdefinierende Eckstein, dh sie sind nicht "schließen", sie sind "genau" - wobei "schließen" eine relative Abweichung von der exakten ist . (_Hinweis: _Die spezielle Gehäusebedingung kann die Leistung beeinträchtigen (oder auch nicht).)

+ vs max

Das Mischen oder "Shadowing" von rel_tol und a_tol aufgrund der Implementierung unter Verwendung einer Summe und nicht max _does_ bricht die obige Funktionssemantik. Die Definition des Benutzers von "schließen" ist auf nicht triviale Weise gebunden, da sie die Semantik von "relativ" und "absolut" zerfleischt und daher bricht. Wenn man nur die obige Semantik betrachtet, ist dieser Aspekt ein Fehler. Ich finde @gasparka Eröffnungsbeispiel ein unwiderlegbares Argument dieses Punktes.

Kommutativität (dh Symmetrie)

Es gibt hier wirklich nur zwei Operatoren: - in a-b und <= in |a-b| <= f(a, b, atol, rtol) . Während Subtraktion antikommutativ ist, ist |a - b| per Definition nicht kommutativ. Dies allein reicht jedoch möglicherweise nicht aus, um den Kommutativ von f(a, b, atol, rtol) . Hier gibt es jedoch ein starkes und ein schwaches Argument.

  • Das Schwächste ist das Einfachste - Kapselung der Funktionstrennung oder das Fehlen von -, während die Kommutativität von |a - b| arithemisch möglicherweise nicht die von f(a, b, atol, rtol) erzwingt, programmatisch ist f(a, b, atol, rtol) nicht wirklich in Frage aber isClose(a, b, atol, rtol) . Hier wird die Berechnung |a - b| intern für die Funktion durchgeführt, dh isClose() := |a-b| <= f(a, b, atol, rtol) . Da dies intern ist und a und b durchlaufen werden, muss auch |a-b| kommutativ sein isClose() . Wenn dies nicht der Fall ist, verliert die Kommutativität von |a-b| alle Bedeutung.
  • Starke Argument: Der Vergleich op ist nicht-streng, dh , es ist <= nicht < , also für die Gleichheit Teil des Vergleichs haben Sie zufrieden zu stellen |a-b| = f(a, b, atol, rtol) , was impliziert , f(a, b, atol, rtol) _ muss auch kommutativ sein (glaube ich?). Wenn Sie dies nicht tun, bedeutet dies, dass entweder die obige Gleichheit niemals wahr ist (es gibt keine Werte von a & b , die dies erfüllen) oder dass die strikte Ungleichung < vorliegt tatsächlich semantisch definiert, oder?

Was Sie gegen alles oder irgendetwas tun (oder nicht tun), ist eine völlig separate Frage.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen