Autor |
Beitrag |
Spaceguide
      
Beiträge: 552
(D3/D7/D8) Prof.
|
Verfasst: So 21.05.06 14:19
Kann ist den Befehlen FISTP (FPU) bzw. CVTSS2SI (SSE) irgendwie beibringen, bei 0.5 richtig aufzurunden? Normalerweise wird 0.5 nämlich auf 0 gerundet.
|
|
Waldteufel
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: So 21.05.06 17:26
Hi Spaceguide.
Guck dir einfach in der Unit Math bei der Funktion SetRoundMode ab, was die bei SetRoundMode(rmNearest); macht.
(Hast ja laut Profil die Prof-Version, bei der sind ja die Quellen dabei)
|
|
Spaceguide 
      
Beiträge: 552
(D3/D7/D8) Prof.
|
Verfasst: So 21.05.06 17:47
Das hatte ich schon untersucht. Standard ist rmNearest. Ist der ganzzzahlige Teil gerade (0.5,2.5,4.5 ...), so wird immer abgerundet, ist er ungerade (1.5,3.5,5.5 ...), dann aufgerundet.
|
|
Marc.
      
Beiträge: 1876
Erhaltene Danke: 129
Win 8.1, Xubuntu 15.10
|
Verfasst: So 21.05.06 18:27
Hey,
notfalls könntest du dir auch einen eigene Funtkion schreiben.
Ich habe mal eine geschrieben, die dir hoffentlich weiterhelfen mag  :
Sie Rundet bei >= 0,5 auf und bei < 0,5 ab:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20:
| function Round(Number: Real): Real; var FindC: Byte; NumAsStr: String; begin FindC := pos(',',FloatToStr(Number));
if FindC = 0 then Result := Number else begin NumAsStr := Copy(FloatToStr(Number),FindC,Length(FloatToStr(Number))-FindC+1); If StrToFloat(NumAsStr) >= 0.5 then begin NumAsStr := FloatToStr(Number); Delete(NumAsStr,FindC+1,Length(FloatToStr((Number)-FindC))); Result := StrToFloat(NumAsStr)+1; end else Result := RoundTo(Number,0); end; end; |
mfg
|
|
Spaceguide 
      
Beiträge: 552
(D3/D7/D8) Prof.
|
Verfasst: So 21.05.06 18:42
|
|
Marc.
      
Beiträge: 1876
Erhaltene Danke: 129
Win 8.1, Xubuntu 15.10
|
Verfasst: So 21.05.06 18:48
War nur ein Vorschlag 
|
|
Spaceguide 
      
Beiträge: 552
(D3/D7/D8) Prof.
|
Verfasst: So 21.05.06 18:51
Bei näherem Hinsehen muss ich aber lachen. Ein einfaches Trunc(x+0.5) macht prinzipiell das gleiche, nur eben korrekt: Deine Funktion funktioniert nur, wenn der Separator ein Komma ist (bei englischen Systemen ist es ein Punkt) und -0.5 rundet sie zu +1!
|
|
starsurfer
      
Beiträge: 334
Win 95, Win 98, Win XP, Win Vista, Linux
D5 Enterprise ,D2005, D6 Personal, Visual C++ Express 2005, C++ Builder 6 E, Dev-C++
|
Verfasst: So 21.05.06 18:54
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| function RountByFive(valve:real):integer; var help:integer; begin result:=trunc(valve); help:=trunc(frac(valve)*10)); if help>4 then inc(Result); end; |
das is dürfte auch gehen
und es ist ein bisschen schneller als der vorherige Vorschlag
//Edit, ok du hast ja deine Lösung schon ^^
_________________ GEIZ IST GEIL! - Ihr Sozialamt
Zuletzt bearbeitet von starsurfer am So 21.05.06 18:55, insgesamt 1-mal bearbeitet
|
|
Marc.
      
Beiträge: 1876
Erhaltene Danke: 129
Win 8.1, Xubuntu 15.10
|
Verfasst: So 21.05.06 18:55
 Du hast recht.
Ich sitze hier einfach schon zu lange am PC und bin vollkommen übermüded.
Ich denk, ich leg mich gleich mal hin.
Und nun back zum Topic.
Mfg 
|
|
Spaceguide 
      
Beiträge: 552
(D3/D7/D8) Prof.
|
Verfasst: So 21.05.06 18:57
Ich find das jetzt nicht fair. Ich habe eine ernste Frage gestellt und werde nur verarscht.
|
|
Green
      
Beiträge: 283
Windows XP Home
Delphi 6 Enterprise
|
Verfasst: So 21.05.06 19:01
wieso das denn?? hast doch deine frage schon selber beantwortet...
und du hast sogar zwei weitere varianten 
|
|
Spaceguide 
      
Beiträge: 552
(D3/D7/D8) Prof.
|
Verfasst: So 21.05.06 19:18
So? Meine Frage lautete aber nicht, wie ich eine Zahl korrekt runden kann, sonder:
"Kann ist den Befehlen FISTP (FPU) bzw. CVTSS2SI (SSE) irgendwie beibringen, bei 0.5 richtig aufzurunden? Normalerweise wird 0.5 nämlich auf 0 gerundet."
|
|
Green
      
Beiträge: 283
Windows XP Home
Delphi 6 Enterprise
|
Verfasst: So 21.05.06 19:25
nunja, eine Funktion kann man so einfach nicht ändern, ausserdem warum denn nicht eine eigene verwenden?
|
|
Spaceguide 
      
Beiträge: 552
(D3/D7/D8) Prof.
|
Verfasst: So 21.05.06 19:29
Weil es performanzkritisch ist.
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: So 21.05.06 20:46
Das ist leider Architektur-Bedingt nicht möglich ...
Du kannst aber
Delphi-Quelltext 1: 2: 3: 4:
| asm FADD [OneHalf] FRNDINT end; |
versuchen, wenn Du das Rounding Control-Flag auf Truncate gesetzt hast.
Die FPU unterstützt nur RoundUp, RoundDown, BankersRounding und Truncate als Modi. Das mathematisch korrekte Runden muss man emulieren.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
Spaceguide 
      
Beiträge: 552
(D3/D7/D8) Prof.
|
Verfasst: Mo 22.05.06 20:49
Hi,
also mit SetRoundMode(rmDown) bekomme ich Round(x) = Trunc(x+0.5) korrekt hin. Nur bin ich mir ein bisschen unsicher, ob das Control-Word auch so bleibt. Gibt es irgendwelche Komponenten, die gerne mal das Control-Word ändern und nicht mehr zurücksetzen?
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Mo 22.05.06 21:29
Wäre mir innerhalb der VCL nichts bewusst. Trunc und Round aus der RTL sind deshalb so lahmarschig, weil sie das CW immer erst wieder Resetten... Dadurch geht enorm Zeit verloren ...
Ansonsten setz einfach einmal vor Ausführung deiner Zeitkritischen Aktionen das CW ... Innerhalb deiner Routine kannst Du dann ggf. an kritischen Stellen noch mal kurz eine Überprüfung einbauen, sollte dies nötig sein ...
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
Spaceguide 
      
Beiträge: 552
(D3/D7/D8) Prof.
|
Verfasst: Di 23.05.06 12:13
Gibt's für die SSE-Einheit auch sowas wie einen Rounding Mode?
|
|
Spaceguide 
      
Beiträge: 552
(D3/D7/D8) Prof.
|
Verfasst: Di 23.05.06 13:13
OK, wenn ich die Bits 14/13 des Registers MXCSR mittels LDMXCSR auf 01 setze, bekomme ich auch die SSE-Einheit dazu, immer abzurunden, jedoch scheint irgendetwas das Register wieder zurückzusetzen, so dass ich das Register immer wieder vor jeder Rundungsaktion setzen muss. Irgendwelche Hinweise, was es zurücksetzt?
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Di 23.05.06 14:18
Wüsste ich jetzt aus dem Kopf nix... Hab mit SSE noch nicht gearbeitet. Könnte aber sein, dass durch das Neueinrichten der SSE-Umgebung das Flag resettet wird? FPU und SSE sharen sich ja die Register-Speicher ...
Oder meinst Du das Flag wird bei jedem Befehl resettet ... Dann kannst Du glaube nicht viel tun ...???
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|