math.copysign Anwendungszweck

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
nezzcarth
User
Beiträge: 1638
Registriert: Samstag 16. April 2011, 12:47

Hallo,

einige Programmiersprachen, darunter auch Python, haben in ihrer Mathe-Bibliothek eine Funktion "copysign", mit der man das Vorzeichen einer Zahl auf das einer anderen übertragen kann. Ich frage mich, was konkrete, übliche Anwendungszwecke dafür sind. Spezialfälle, die mir einfallen, sind, dass man damit eine Vorzeichenfunktion, die Python nicht hat, nachbilden kann; zudem kann ich es mir als langsameren Ersatz für 'abs' vorstellen. Mir ist klar, dass die Frage etwas seltsam ist, aber ich bin trotzdem neugierig, warum man so etwas für so wichtig hält, dass relativ viele Sprachen/Bibliotheken es haben :) Da gibt es doch bestimmt einige übliche Anwendungsfälle, aber ich hatte Probleme, Beispiele zu finden.
Danke.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich weiss es nicht wirklich, eine Spekulation, die im Rahmen von effizientem Code ggf. greift: wenn man moeglichst schnell moeglichst viel rechnen will, benutzt man ueblicherweise die entsprechenden Prozessor-Erweiterungen wie SSE2 & Co. Und ein entscheidender Anteil an schnellem Code hat auch das Vermeiden von Verzweigungen. Darum kann es sich oft lohnen, einen Algorithmus etwes "verquer" durch mathematische Operationen auszudruecken. Ein kleines, harmloses Beispiel: ich brauche gerade Ringbuffer fuer uC-Programmierung in Assembler. Der hat einen schreibe und einen lese-Zeiger bzw. Index. Der Fuellgrad ergibt sich dadurch aus der Differenz dieser beiden Werte:

Code: Alles auswählen

filled = write_pos - read_pos
Aber halt - das ist ja ein Ringbuffer! Es kann also vorkommen, dass write_pos < read_pos ist, und ich eine negative Zahl erhalte. So ist es also richtig:

Code: Alles auswählen

filled = write_pos - read_pos
if filled < 0:
    filled += buffer_size
Und schon habe ich mir eine Verzweigung eingehandelt.

Es geht aber auch so:

Code: Alles auswählen

filled = (write_pos  + buffer_size - read_pos) % buffer_size
Ich erzwinge also, dass write_pos immer relativ groesser ist als read_pos, aber ggf. bin ich "zu gross" und falte das Ergebnis dann wieder in die Buffergroesse. Und der Vorteil: alles Maschineninstruktionen (zB % einfach AND), die ohne Verzweigung laufen, und die Pipeline voll halten.

Und da kann ich mir vorstellen, dass es eben Algorithmen gibt, die von copysign in dieser Art profitieren.

Wirklich belastbares habe ich dazu aber auch nicht gefunden. In der C++-std-lib steht immerin das hier:

https://en.cppreference.com/w/cpp/numeric/math/copysign

std::copysign is the only portable way to manipulate the sign of a NaN value (to examine the sign of a NaN, signbit may also be used)

Das hat wahrscheinlich was mit IEE754 zu tun.
nezzcarth
User
Beiträge: 1638
Registriert: Samstag 16. April 2011, 12:47

Danke für die ausführliche Antwort und das Beispiel. Ich finde, das klingt sehr plausibel (und kenne, wo du es sagst, auch selbst solche hoch-optimierten Implementierungen, z. B. für die Levenshtein-Distanz).
Antworten