Autor Beitrag
knittel
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 71
Erhaltene Danke: 2

Win XP, Win7, openSUSE
Delphi 7
BeitragVerfasst: Mi 21.08.13 01:44 
Hallo allerseits,

Ich hab um einen beliebigen Winkel in der Rahmen von 0 und 360 zu bringen den module Operator verwendet. Einfach result := Winkel mod 360.
Doch sobald es zu negativen Zahlen kommt, ist der Winkel stattdessen

_________________
"Wir können nicht fliehen!" "Wieso nicht?" "Sie haben mir die Schnürsenkel zusammengebunden!" "Die Schweine."
Tranx
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 648
Erhaltene Danke: 85

WIN 2000, WIN XP
D5 Prof
BeitragVerfasst: Mi 21.08.13 04:21 
Bei x mod y bekommst Du nur ganzzahlige Werte, da Du nur ganzzahlige Werte einsetzen darfst. Aber unabhängig davon, mit
ausblenden Delphi-Quelltext
1:
   y := abs(x) mod 360;					


solltest Du das gewünschte Ergebnis bekommen.

Und für nicht integer:

ausblenden Delphi-Quelltext
1:
   y := abs(x - int(x/360)*360);					

_________________
Toleranz ist eine Grundvoraussetzung für das Leben.
Boldar
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 1555
Erhaltene Danke: 70

Win7 Enterprise 64bit, Win XP SP2
Turbo Delphi
BeitragVerfasst: Mi 21.08.13 06:03 
oder aber
ausblenden Delphi-Quelltext
1:
2:
while (x<0) x:=x+360;
x:=x mod 360;

Für bessere Performance evtl. die 360 durch größere Zahlen ersetzen, z.B. ((maxint div 360)*360)
Gammatester
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 328
Erhaltene Danke: 101



BeitragVerfasst: Mi 21.08.13 09:13 
user profile iconTranx hat folgendes geschrieben Zum zitierten Posting springen:
ausblenden Delphi-Quelltext
1:
2:
3:
y := abs(x) mod 360;
//..
y := abs(x - int(x/360)*360);
Die beiden Formeln sind alllerdings offensichtlich falsch, da zB -30 nach 30 transformiert wird! Das bedeutet zB für den einfachen Sinus, das Du falsche Vorzeichen hast. Die einfachste und schnellste Möglichkeit nur mit Delphibordmitteln ist meiner Meinung nach
ausblenden Delphi-Quelltext
1:
2:
y := x - int(x/360.0)*360.0;     // Kann zwischen -360 .. +360 liegen
if y < 0.0 then y := y + 360.0;  // Korrektur falls negative

Für diesen Beitrag haben gedankt: FinnO
jasocul
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 6395
Erhaltene Danke: 149

Windows 7 + Windows 10
Sydney Prof + CE
BeitragVerfasst: Mi 21.08.13 10:10 
Habe nur ich das Gefühl, dass hier mit Kanonen auf Spatzen geschossen wir?
ausblenden Delphi-Quelltext
1:
2:
3:
NeuerWinkel := AlterWinkel mod 360;
if NeuerWinkel < 0 then
  NeuerWinkel := NeuerWinkel + 360;
Xion
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
EE-Maler
Beiträge: 1952
Erhaltene Danke: 128

Windows XP
Delphi (2005, SmartInspect), SQL, Lua, Java (Eclipse), C++ (Visual Studio 2010, Qt Creator), Python (Blender), Prolog (SWIProlog), Haskell (ghci)
BeitragVerfasst: Mi 21.08.13 11:17 
Fast, ich würde sagen:

ausblenden Delphi-Quelltext
1:
2:
3:
NeuerWinkel := AlterWinkel mod 360;
while NeuerWinkel < 0 do
  NeuerWinkel := NeuerWinkel + 360;


Aber das hatte user profile iconBoldar schon so in etwa :mrgreen:

oder ganz ohne mod:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
while NeuerWinkel >= 360 do
  NeuerWinkel := NeuerWinkel - 360;
while NeuerWinkel < 0 do
  NeuerWinkel := NeuerWinkel + 360;


Das Ding heißt übrigens nicht module sondern modulo

_________________
a broken heart is like a broken window - it'll never heal
In einem gut regierten Land ist Armut eine Schande, in einem schlecht regierten Reichtum. (Konfuzius)
jasocul
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 6395
Erhaltene Danke: 149

Windows 7 + Windows 10
Sydney Prof + CE
BeitragVerfasst: Mi 21.08.13 11:21 
@Xion:
Das while ist unnötig, da das vorherige Modulo schon dafür sorgt, dass der neue Winkel im richtigen Bereich ist. :wink:
Gammatester
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 328
Erhaltene Danke: 101



BeitragVerfasst: Mi 21.08.13 11:24 
user profile iconjasocul hat folgendes geschrieben Zum zitierten Posting springen:
Habe nur ich das Gefühl, dass hier mit Kanonen auf Spatzen geschossen wir?
ausblenden Delphi-Quelltext
1:
2:
3:
NeuerWinkel := AlterWinkel mod 360;
if NeuerWinkel < 0 then
  NeuerWinkel := NeuerWinkel + 360;
Richtig! Die Kanonen müssen ja auch nur dann zu Einsatz kommen, wenn die Winkel keine Integer sind, was also wahrscheinlich meist der Fall ist, außer vielleicht für einzelne Spezialfragen oder eine Tabelle der von reduzierten Integerwinkeln :wink:
Xion
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
EE-Maler
Beiträge: 1952
Erhaltene Danke: 128

Windows XP
Delphi (2005, SmartInspect), SQL, Lua, Java (Eclipse), C++ (Visual Studio 2010, Qt Creator), Python (Blender), Prolog (SWIProlog), Haskell (ghci)
BeitragVerfasst: Mi 21.08.13 11:29 
user profile iconjasocul hat folgendes geschrieben Zum zitierten Posting springen:
@Xion:
Das while ist unnötig, da das vorherige Modulo schon dafür sorgt, dass der neue Winkel im richtigen Bereich ist.

Hmm, also das ist mir zu vage. Warum sollte ich nicht zweimal einen Winkel abziehen, bevor ich ihn wieder normalisiere? Das Modulo hat ja keinen Effekt bei negativen Zahlen (zumindest bei meinem Delphi bin ich mir da zu 99,9% sicher). So komm ich leicht auf -400 Grad. Mir ist da eine sichere, vielleicht minimal langsamere Variante doch lieber ;)

_________________
a broken heart is like a broken window - it'll never heal
In einem gut regierten Land ist Armut eine Schande, in einem schlecht regierten Reichtum. (Konfuzius)
jasocul
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 6395
Erhaltene Danke: 149

Windows 7 + Windows 10
Sydney Prof + CE
BeitragVerfasst: Mi 21.08.13 11:58 
@Gammatester:
Modulo ist für ganzzahligen Werte. user profile iconknittel nutzt das ja schon. Sollten allerdings auch nicht-ganzzahlige Typen verwendet werden, hast du natürlich Recht.

@Xion:
Bei XE2 funktioniert Modulo auch bei negativen Werten.
Tranx
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 648
Erhaltene Danke: 85

WIN 2000, WIN XP
D5 Prof
BeitragVerfasst: Mi 21.08.13 12:47 
user profile iconGammatester hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconTranx hat folgendes geschrieben Zum zitierten Posting springen:
ausblenden Delphi-Quelltext
1:
2:
3:
y := abs(x) mod 360;
//..
y := abs(x - int(x/360)*360);
Die beiden Formeln sind alllerdings offensichtlich falsch, da zB -30 nach 30 transformiert wird! Das bedeutet zB für den einfachen Sinus, das Du falsche Vorzeichen hast. Die einfachste und schnellste Möglichkeit nur mit Delphibordmitteln ist meiner Meinung nach
ausblenden Delphi-Quelltext
1:
2:
y := x - int(x/360.0)*360.0;     // Kann zwischen -360 .. +360 liegen
if y < 0.0 then y := y + 360.0;  // Korrektur falls negative


Alternativ: Um die FALSCHE Formel zu verbessern:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
// Integerzahl
y := x mod 360;
if y <0 then 
  y := y + 360;

// Realzahl
y := abs(x - int(x/360)*360);
if y <0.0 then 
  y := y + 360;

_________________
Toleranz ist eine Grundvoraussetzung für das Leben.
knittel Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 71
Erhaltene Danke: 2

Win XP, Win7, openSUSE
Delphi 7
BeitragVerfasst: Mi 21.08.13 13:09 
ui^^ ne ganze Mengen Antworten. Danke an alle schonmal! :)
Es war zwar garnicht so sehr das Problem wie ich das löse, dafür verwende ich:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
function ClampToAngle(const A: single): single;
begin
result := Trunc(A) mod 360 + Frac(A);
if result < 0 then result := result + 360;
end;


(auf while wollte ich aus Performance-Gründen verzichten)

Ich hab mich nur gefragt warum mod so arbeitet. Ich dachte immer mod würde (an einem Zahlenstrahl erklärt) so arbeiten:

x mod 4
ausblenden Quelltext
1:
2:
x: -9|-8|-7|-6|-5|-4|-3|-2|-1|0|1|2|3|4|5|
y:  3| 0| 1| 2| 3| 0| 1| 2| 3|0|1|2|3|0|1|

_________________
"Wir können nicht fliehen!" "Wieso nicht?" "Sie haben mir die Schnürsenkel zusammengebunden!" "Die Schweine."
Gammatester
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 328
Erhaltene Danke: 101



BeitragVerfasst: Mi 21.08.13 13:39 
user profile iconTranx hat folgendes geschrieben Zum zitierten Posting springen:
Alternativ: Um die FALSCHE Formel zu verbessern:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
// Realzahl
y := abs(x - int(x/360)*360);
if y <0.0 then 
  y := y + 360;
Das ist nun definitiv Unsinn. y=abs() kann nicht negativ sein, also bringt die if-Anweisung überhaupt nichts, und -30 wird immer noch in +30 umgewandelt und nicht in 330.
Mathematiker
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2622
Erhaltene Danke: 1448

Win 7, 8.1, 10
Delphi 5, 7, 10.1
BeitragVerfasst: Mi 21.08.13 14:20 
Hallo,
so ein ähnliches Problem kenne ich bei der Berechnung des Wochentages mit der Zellerschen Formel.
Meine Lösung war (auf Dein Problem angewendet):
ausblenden Delphi-Quelltext
1:
2:
3:
4:
 result := (winkel + 360mod 360;
oder
 result := (winkel + 3600mod 360;
oder noch größere Summanden

Da habe ich kein if, while usw. drin, sondern "nur" eine Addition.
Wahrscheinlich ist das wieder nicht so elegant, aber es funktioniert.

Beste Grüße
Mathematiker

_________________
Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
Gammatester
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 328
Erhaltene Danke: 101



BeitragVerfasst: Mi 21.08.13 14:42 
user profile iconMathematiker hat folgendes geschrieben Zum zitierten Posting springen:
Da habe ich kein if, while usw. drin, sondern "nur" eine Addition.
Wahrscheinlich ist das wieder nicht so elegant, aber es funktioniert.
Wie wir inzwischen erfahren haben, will user profile iconknittel ja doch eigentlich Singlewinkel normalisieren und wählt einen Weg über trunc() mod 360 + frac(). Selbst wenn man Deinen Ansatz einsetzen würde, hätte man
ausblenden Delphi-Quelltext
1:
result := (Trunc(A) + 3600mod 360 + Frac(A)					
Trotzdem käme man wegen des möglichen negativen Frac(A) praktisch nicht um ein if herum, weil das Ergebnis noch negativ sein kann (oder man müßte noch mehr Aufwand treiben um ein if zu vermeiden).
Tranx
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 648
Erhaltene Danke: 85

WIN 2000, WIN XP
D5 Prof
BeitragVerfasst: Mi 21.08.13 15:03 
user profile iconGammatester hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconTranx hat folgendes geschrieben Zum zitierten Posting springen:
Alternativ: Um die FALSCHE Formel zu verbessern:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
// Realzahl
y := abs(x - int(x/360)*360);
if y <0.0 then 
  y := y + 360;


korrekt:
if x<0.0 then
  y := 360.0 + x - 360*int(x/360)
else
  y := x - 360*int(x/360);
Das ist nun definitiv Unsinn. y=abs() kann nicht negativ sein, also bringt die if-Anweisung überhaupt nichts, und -30 wird immer noch in +30 umgewandelt und nicht in 330.


Entschuldigung, dass ich das abs nicht gelöscht hatte

bei 30 ergibt das 30 - 360*0 = 30 bei -30 : 360 - 30 - 360*0 = 330
bei 750 ergibt das 750 - 360*2 = 30 bei -750: 360 - 750 - 360*-2 = 330

Das sollte nun korrekt sein.

_________________
Toleranz ist eine Grundvoraussetzung für das Leben.
IhopeonlyReader
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 600
Erhaltene Danke: 23


Delphi 7 PE
BeitragVerfasst: Mi 21.08.13 15:17 
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
  NeuerWinkel := (Abs(Trunc(AltWinkel))-1mod 360 +1;
if AltWinkel<0 then
  NeuerWinkel := (360 - NeuerWinkel) + Frac(AltWinkel)
else
  NeuerWinkel := NeuerWinkel + Frac(AltWinkel);
if NeuerWinkel > 360 then
  NeuerWinkel := NeuerWinkel - 360
else
  if NeuerWinkel < 0 then
    NeuerWinkel := NeuerWinkel + 360;

Ach ich liebe die Vielfalt der Mathematik :D

_________________
Sucht "neueres" Delphi :D
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
Gammatester
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 328
Erhaltene Danke: 101



BeitragVerfasst: Mi 21.08.13 15:18 
Langsam glaube ich auch an die Kanonen/Spatzen-Theorie von user profile iconjasocul. Alles wäre einfacher, wenn Delphi ein mathematisch korrektes mod hätte, das auch für Fließkommazahlen definiert wäre, ähnlich fmod in C. Man kann es natürlich mit floor aus der Math-Unit nachbilden und hätte dann (ohne if):
ausblenden Delphi-Quelltext
1:
2:
3:
4:
function ClampToAngle(const A: single): single;
begin
  result := A - floor(A/360.0)*360.0;
end;

Für diesen Beitrag haben gedankt: knittel
IhopeonlyReader
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 600
Erhaltene Danke: 23


Delphi 7 PE
BeitragVerfasst: Mi 21.08.13 15:21 
ok, gammatester hat wohl damit den thread beendet :D
das ist die einfachste und warscheinlich schnellste methode

_________________
Sucht "neueres" Delphi :D
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
Gammatester
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 328
Erhaltene Danke: 101



BeitragVerfasst: Mi 21.08.13 15:26 
user profile iconIhopeonlyReader hat folgendes geschrieben Zum zitierten Posting springen:
Gammetester.. es bleibt dabei -0,12° <> 0,12° sondern = 359,88° !
Huh :autsch: Meine Funktion liefert die 359,88°, vielleicht hast Du nicht mitbekommen, daß 0,12° nicht das gewünschte Ergebnis ist. - Oder ich bin im Tran und mache dann besser Schluß für heute.

(Noch'n Mist): Ist wohl durch ein Edit von user profile iconIhopeonlyReader überholt.