cmath.sqrt (komplex, python usw.)

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • cmath.sqrt (komplex, python usw.)

    Na, bin mal gespannt, ob in diesem Teil des Forums auch jemand antwortet.

    Meine Frage ist nicht ganz einfach einem Themenbereich zuzuordnen, da sie aber beim Portieren eines Python Programms auftritt, versuche ich es mal hier.

    Es ist aber eher was mathematisches:

    In einem Python-Programm (das ich portiere) wird viel mit 2D Kooridinaten rumgeeiert. Dazu werden Variablen vom Typ "complex" verwendet, also komplexe Zahlen.

    Es geht aber wie gesagt um ganz allgemeine 2D (Grafik) Koordinaten und ich konnte bisher alles beim Portieren nach ObjC sauber mit einer eigenen "Vector2D"-Klasse abfangen, die auch die grundlegenden Vektor-Operationen beherrscht (Absolutwert, Kreuzprodukt, Vektor-Addition usw).

    Jetzt stieß ich allerdings auf eine Stelle im Code, bei der ein 2D-Vektor folgendermaßen umgerechnet wird:

    direction = cmath.sqrt( bridgeDirection )

    Fein.
    Meine Erfahrungen in komplexer Mathematik liegen leider schon sehr weit in der Vergangenheit (bisher ging es, wie gesagt immer nur um einfache 2D-Vektor-Mathematik).

    Was um Himmels Willen berechnet cmath.sqrt aus einem Richtungsvektor und wie portiere ich das in C/ObjC???

    Jemand eine Idee?
    Bevor man jemanden kritisiert, sollte man zuerst ein paar Meilen in dessen Schuhen gehen!
    Erstens ist man dann in sicherem Abstand und zweitens hat man die Schuhe...
  • RE: cmath.sqrt (komplex, python usw.)

    Die Lösung ist relativ einfach, wenn die komplexe Zahl in Polardarstellung bestehend aus einem Winkel und der Vektorlänge vorliegt. Dann hat die Quadratwurzel den halben Winkel und die Länge ist die Wurzel der ursprünglichen Länge. Also ungefähr so

    sqrt( [alpha, r] ) = [alpha / 2, sqrt(r)],

    wobei alpha ein Winkel und r eine positive reelle Zahl ist. Für eine komplexe Zahl z = a + ib kannst Du in C/C++/Objective-C die Polardarstellung durch

    Quellcode

    1. alpha = atan2(b, a) ;
    2. r = sqrt(a * a + b * b);

    berechnen.

    Mehr dazu findest Du in Wikipedia.
    „Meine Komplikation hatte eine Komplikation.“
  • RE: cmath.sqrt (komplex, python usw.)

    Ich hatte recht, Winkel (im Einheitskreis) wird halbiert.

    Zur besseren Visualisierung ist hier ein Beispiel (Winkel des "Richtungsvektors" mit Taste "a" und "d" drehen):

    Quellcode

    1. from OpenGL.GL import *
    2. from OpenGL.GLU import *
    3. from OpenGL.GLUT import *
    4. import math
    5. import cmath
    6. def idle():
    7. glutPostRedisplay()
    8. def keydown(key, x, y):
    9. if key=='d':
    10. display.angle += 0.01
    11. if key=='a':
    12. display.angle -= 0.01
    13. if key=='q' or key=='\x1b':
    14. exit(0)
    15. def draw_axes():
    16. glColor3f(0,1,0)
    17. glBegin(GL_LINES)
    18. glVertex2f(-1,0)
    19. glVertex2f(1,0)
    20. glVertex2f(0,-1)
    21. glVertex2f(0,1)
    22. glEnd()
    23. def draw_vec(vec, col):
    24. glColor3f(col[0],col[1],col[2])
    25. glBegin(GL_LINES)
    26. glVertex2f(0, 0)
    27. glVertex2f(vec[0], vec[1])
    28. glEnd()
    29. def display():
    30. glClear(GL_COLOR_BUFFER_BIT)
    31. draw_axes()
    32. # calculate unit-vector from angle
    33. vn = [0.]*2
    34. vn[0] = math.sin(display.angle)
    35. vn[1] = math.cos(display.angle)
    36. # draw vec in red
    37. draw_vec( vn, (1,0,0) )
    38. # calcuate complex
    39. cvn = complex(vn[0],vn[1])
    40. cvn = cmath.sqrt(cvn)
    41. vn[0] = cvn.real
    42. vn[1] = cvn.imag
    43. # and draw in yellow
    44. draw_vec( vn, (1,1,0) )
    45. # DONE
    46. glutSwapBuffers()
    47. if __name__ == '__main__':
    48. display.angle = 0
    49. glutInit()
    50. glutInitWindowSize(640, 480)
    51. glutInitDisplayString('rgba double')
    52. glutCreateWindow('spam')
    53. glutDisplayFunc(display)
    54. glutKeyboardFunc(keydown)
    55. glutIdleFunc(idle)
    56. glPointSize(10.)
    57. glutMainLoop()
    Alles anzeigen
    C++
  • Super! Das ging ja fix!

    Vielen Dank für die Antworten (vor allem auch für das Beispielprogramm)!

    Jetzt ist mir schon etwas klarer, was das soll.
    Bevor man jemanden kritisiert, sollte man zuerst ein paar Meilen in dessen Schuhen gehen!
    Erstens ist man dann in sicherem Abstand und zweitens hat man die Schuhe...
  • So, und zum Abschluss noch die komplettierte Lösung des Problems:

    [UPDATE: autorelease eingefügt. Ich verwende die Funktion zwar mit GrabageCollection (deshalb war kein release nötig), aber falls jemand die Funktion per Copy/Paste übernimmt, ist es hier besser das autorelease einzufügen (stört ja bei GC nicht).]

    Hier die "Ersatzfunktion" in meiner ObjC-Klasse Vector2

    Quellcode

    1. - (Vector2*)sqrt {
    2. CGFloat a = atan2(y, x);
    3. CGFloat r = sqrtf([self abs]);
    4. return [[[Vector2 alloc] initWithX:cos(a)*r Y:sin(a)*r] autorelease];
    5. }


    sowie hier mein "Gegentest" in Python, den ich im Beispielprogramm von zermelo verwendet habe, um die Funktion zu testen :)

    Quellcode

    1. def sqrt_ersatz(cv):
    2. a = math.atan2(cv.imag, cv.real);
    3. r = math.sqrt(abs(cv))
    4. return complex(math.cos(a)*r, math.sin(a)*r)


    Verwendet man diese im Beispielprogramm statt cmath.sqrt, erhält man das selbe Ergebnis :)

    Danke noch mal an alle!
    Bevor man jemanden kritisiert, sollte man zuerst ein paar Meilen in dessen Schuhen gehen!
    Erstens ist man dann in sicherem Abstand und zweitens hat man die Schuhe...
  • Und ich hatte mir noch überlegt, ob ich's dazuschreibe (hätte ich wohl besser): Ich arbeite mit GrabageCollection -> kein autorelease
    Bevor man jemanden kritisiert, sollte man zuerst ein paar Meilen in dessen Schuhen gehen!
    Erstens ist man dann in sicherem Abstand und zweitens hat man die Schuhe...
  • man machts aber trotzdem nicht so!


    Wer ist "man"? Und wo steht das bitte in Stein gemeiselt?

    Wenn ich ein Framework schreibe mag es angesagt sein, für Fälle der Verwendung des Frameworks in einem non-GC-Programm zweigleisig zu fahren und die releases reinzuschreiben.

    Wenn ich aber ein Programm mit eingeschaltetem GC schreibe ist es Blödsinn, ständig die releases/autoreleases mit reinzuschreiben. Letztlich werden sie von mir eh weder verwendet noch getestet (!) und es ist somit lediglich "noise" im Code, der viel Schreibarbeit verursacht und den (falschen!!) Eindruck schafft, der Code wäre für Arbeiten ohne GC geschrieben (und getestet!).
    Ist er aber nicht!

    Wie gesagt, ich rede hier nicht von Codebeispielen oder Frameworks, die in allen möglichen Situationen verwendet werden können (deshalb habe ich in mein's oben inzwischen auch den autorelease eingefügt), sondern von "private" Code, den ich in meinem GarbageCollected Programm schreibe. Und da ist es blödsinnig, die Sourcen mit releases und autoreleases vollzumüllen.
    Bevor man jemanden kritisiert, sollte man zuerst ein paar Meilen in dessen Schuhen gehen!
    Erstens ist man dann in sicherem Abstand und zweitens hat man die Schuhe...
  • Für was für eine Convenience sorgt denn ein Convenience-Allocator, wenn nicht für den automatischen Release?

    Wenn es nur darum geht (jetzt mal konkret im GarbageCollect-Fall), statt

    Quellcode

    1. [[Klasse alloc] initWithA:a andB:b];

    Quellcode

    1. [Klasse klasseWithA:a andB:b];

    zu schreiben, dafür aber an anderer Stelle die folgende zusätzliche Methode vorhalten zu müssen:

    Quellcode

    1. - (Klasse*)klasseWithA:(id)a andB:(id)b {
    2. return [[Klasse alloc] initWithA:a andB:b];
    3. }

    ... dann finde ich das (mal rein Convenience-mäßig) recht grenzwertig.

    Von wegen "immer die beste Lösung" wäre ich da eher vorsichtig.

    Aber jetzt wird es mir dann doch etwas zu sehr off-topic. Vielleicht solltest du für so eine Diskussion 'nen extra Thread aufmachen.
    Bevor man jemanden kritisiert, sollte man zuerst ein paar Meilen in dessen Schuhen gehen!
    Erstens ist man dann in sicherem Abstand und zweitens hat man die Schuhe...