AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

floats auf Null prüfen (C++)

Ein Thema von SnuffMaster23 · begonnen am 3. Apr 2008 · letzter Beitrag vom 5. Apr 2008
Antwort Antwort
Seite 2 von 3     12 3   
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#11

Re: floats auf Null prüfen (C++)

  Alt 4. Apr 2008, 18:37
Man kann den Epsilonwert berechnen lassen.
Man nimmt die Zahl 1.0 und halbiert so lange, bis 1.0+Epsilon = 1.0 ergibt:
Delphi-Quellcode:
var
   Epsilon : Double;
procedure CalcMachineEpsilon; // abgekupfert aus der JCL und vereinfacht
var
  One: Double;
  T: Double;
begin
  One := 1.0;
  Epsilon := One; // vielleicht sollte man mit einem deutlich kleineren Wert beginnen
  repeat
    Epsilon := 0.5 * Epsilon;
    T := One + Epsilon;
  until One = T;
end;
Andreas
  Mit Zitat antworten Zitat
Benutzerbild von SnuffMaster23
SnuffMaster23

Registriert seit: 13. Feb 2006
Ort: Kempten
253 Beiträge
 
#12

Re: floats auf Null prüfen (C++)

  Alt 4. Apr 2008, 20:23
@DMW: Hm, das geht tatsächlich nicht so. Das war nur schnell in der Vorlesung hingeschrieben, ich hab irgendwie gedacht ein double wäre 32 Bits lang und der Compiler wirds schon machen^^
Das mit den ints is mir klar, ich kenn das Zweierkomplement (und die float-Normen, drum wollt ich das vorderste Bit wegmachen).

Soa, ich habs grad mal schnell ausprobiert, es macht keinen Unterschied^^
Code:
#include <iostream>
#include <conio.h>
#include <windows.h>

using namespace std;

#define e 0.00001
#define NUM 999999999

inline bool isNull (double val, double ep = 0.000000001)
{
    *reinterpret_cast <long long*> (&val) &= 0x7FFFFFFFFFFFFFFFull;
    return (val < ep);
}

int main()
{
  LARGE_INTEGER Freq,
                Start,
                End;
  int i;
  double Zero = 0.0;

  QueryPerformanceFrequency(&Freq);
  cout << "Plx auf Echtzeit schalten und Taster drücken...";
  getch();
  cout << endl;

  QueryPerformanceCounter(&Start);
  for (i=0; i<NUM; i++)
    (Zero<e || Zero>-e);
  QueryPerformanceCounter(&End);
  cout << "(x<e || x>-e): " << (Start.QuadPart / (double)End.QuadPart) << " Sek." << endl;

  QueryPerformanceCounter(&Start);
  for (i=0; i<NUM; i++)
    isNull(Zero, e);
  QueryPerformanceCounter(&End);
  cout << "isNull: " << (Start.QuadPart / (double)End.QuadPart) << " Sek." << endl;

  return 0;
}
Die Priorität des Prozesses hab ich auf Echtzeit geschaltet um Einflüsse vom Multitasking weitestgehend auszuschließen und es kommt immer bei beiden das gleiche raus.
Code:
Plx auf Echtzeit schalten und Taster dr³cken...
(x<e || x>-e): 0.999548 Sek.
isNull: 0.999548 Sek.
@Chemiker: Wo ist IsZero drin? Die hab ich nicht gefunden, auch nicht beim fix googeln.

Aber ich denk ich pack einfach die zwei Vergleiche in ne inline Funktion, die versteh ich später gleich wieder^^. Es macht ja eh keinen Unterschied.

MfG,
SnuffMaster23
"Conspiracy is the poor man's mapping of the world" - Fredric Jameson
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#13

Re: floats auf Null prüfen (C++)

  Alt 4. Apr 2008, 20:25
Zitat von SnuffMaster23:
@Chemiker: Wo ist IsZero drin? Die hab ich nicht gefunden, auch nicht beim fix googeln.
IsZero() wie auch SameValue() sind Funktionen die die VCL nur beim C++Builder bietet.
  Mit Zitat antworten Zitat
busybyte

Registriert seit: 15. Sep 2006
165 Beiträge
 
#14

Re: floats auf Null prüfen (C++)

  Alt 4. Apr 2008, 20:31
Unit Math
bei Delphi for Win32
I love DiscCat
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#15

Re: floats auf Null prüfen (C++)

  Alt 4. Apr 2008, 21:04
Zitat von busybyte:
Unit Math
bei Delphi for Win32
Ja, wie gesagt, VCL Funktionalität. Somit auch #include <Math.hpp> im C++Builder, aber es soll nichts Borland spezifisches werden, das hatten wir doch nun schon geklärt...
  Mit Zitat antworten Zitat
DMW

Registriert seit: 6. Sep 2006
Ort: Münster
269 Beiträge
 
Delphi XE Professional
 
#16

Re: floats auf Null prüfen (C++)

  Alt 4. Apr 2008, 21:06
Zitat von SnuffMaster23:
Soa, ich habs grad mal schnell ausprobiert, es macht keinen Unterschied^^
Dein Testprogramm solltest du noch etwas modifizieren:
  • im Optimalfall kann der Compiler beide Schleifen wegoptimieren, da er die Inline-Funktion erweitern darf und somit in beiden Fällen feststellen kann, daß keine Nebenwirkungen auftreten und das Ergebnis verworfen wird. Um die Ausführung der Schleife zu erzwingen, solltest du den Ausdruck an eine Dummyfunktion in einem anderen Modul übergeben, so daß der Compiler sie nicht wegoptimieren kann. Bei dir scheinen aber beide ausgeführt worden zu sein, weshalb ich vermute, daß du deine Tests im Debug Mode machst - das ist nicht empfehlenswert.
  • Die Priorität des Prozesses kannst du auch mittels SetPriorityClass und GetCurrentProcess setzen.
  • Vielleicht die Schleife ein klein wenig öfter durchlaufen lassen.
  • Unter Umständen solltest du die Genauigkeit des Streamoperators mittels std::setprecision erhöhen.
  • Weiterhin wäre vielleicht der generierte Assemblercode sowie die Optimierungsoptionen interessant (und natürlich der Compiler, den du verwendest). Es ist durchaus möglich, daß der Compiler bei beiden Versionen die gleiche Absicht erkennt und zum gleichen Resultat hinoptimiert.
  • Haltepunkte im Release Mode zwecks Inspektion des generierten Codes kannst du in BCC und MSVC mit
    Code:
    asm int 3;
    einbauen.

Edit: siehe unten
Moritz
  Mit Zitat antworten Zitat
busybyte

Registriert seit: 15. Sep 2006
165 Beiträge
 
#17

Re: floats auf Null prüfen (C++)

  Alt 4. Apr 2008, 21:26
@#15
folglich Maschinensprache=Assembler =Rad neu erfinden,
jetzt bin ich aber wirklich raus aus diesem Thread
I love DiscCat
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#18

Re: floats auf Null prüfen (C++)

  Alt 4. Apr 2008, 22:15
Zitat von busybyte:
@#15
folglich Maschinensprache=Assembler =Rad neu erfinden,
jetzt bin ich aber wirklich raus aus diesem Thread
Irgendwie verstehe ich dich nicht. Es geht um die STL bzw. Standard C(++) Lösung, ohne Borland-spezifische Erweiterungen. Wie kommst du somit auf Assembler? Was ist dein Problem?
  Mit Zitat antworten Zitat
DMW

Registriert seit: 6. Sep 2006
Ort: Münster
269 Beiträge
 
Delphi XE Professional
 
#19

Re: floats auf Null prüfen (C++)

  Alt 4. Apr 2008, 22:20
Ein paar Dinge muß ich noch ergänzen:
  • Müßte das
    Zitat von SnuffMaster23:
    Code:
      cout << "(x<e || x>-e): " << (Start.QuadPart / (double)End.QuadPart) << " Sek." << endl;
    nicht viel eher so
    Code:
      cout << "(x<e || x>-e): " << ((End.QuadPart - Start.QuadPart) / (double)Freq.QuadPart) << " Sek." << endl;
    lauten?
  • Es heißt _asm, nicht asm (das geht nur beim BCC).
  • Zudem glaube ich nach einigen Tests nun, daß die Schleife eher ein paar Durchläufe weniger brauchen könnte
  • Mit den genannten Änderungen bekomme ich auf meinem Rechner (XP SP2, Athlon XP 2400+) folgende Ergebnisse (im Bereich der Meßschwankungen gerundet):
    VC2008, Release Mode:
    (x<e || x>-e): 5.013 s
    isNull: 20.325 s

    BCB6, Release Mode:
    (x<e || x>-e): 7.768 s
    isNull: 22.384 s

    Bei genauerem Hinsehen ist das auch schlüssig, denn unsere Trickserei mit reinterpret_cast wird im Speicher ausgeführt, wohingegen beispielsweise der BCC im ersten Fall den FCHS-Opcode verwendet, um das Vorzeichen des Gleitkommawertes in einem Register zu verändern. Hinzu kommt, daß auf 32-Bit-Systemen das Schreiben von 64-Bit-Werten in den Speicher länger dauert - und das ist bei unserem Trick nur verzichtbar, wenn wir wissen, ob wir mit einem Big- oder Little-Endian-System arbeiten. Außerdem sind weder MSVC noch BCC in der Lage, von der inline-Funktion viel mehr als die CALL-Anweisung wegzuoptimieren.

    Für Fälle wie diesen prägte Donald Knuth den Begriff "premature optimization". Er hat Recht: offensichtlich kommen wir hier viel besser weg, wenn wir dem Compiler eindeutig sagen, was wir haben wollen, anstatt vermeintliche Low-Level-Optimierungen einzubauen.


Zitat von busybyte:
jetzt bin ich aber wirklich raus aus diesem Thread
Das wäre, glaube ich, für alle Beteiligten ganz angenehm.
Moritz
  Mit Zitat antworten Zitat
Benutzerbild von Chemiker
Chemiker

Registriert seit: 14. Aug 2005
1.858 Beiträge
 
Delphi 11 Alexandria
 
#20

Re: floats auf Null prüfen (C++)

  Alt 4. Apr 2008, 23:07
Hallo,

@Mutetze1:
Zitat:
Ja, wie gesagt, VCL Funktionalität. Somit auch #include <Math.hpp> im C++Builder, aber es soll nichts Borland spezifisches werden, das hatten wir doch nun schon geklärt...
Wann? Doch erst im #12 Beitrag. Zuerst ist gefragt worden, wie man mit einer Gleitkommazahl einen Vergleich auf Null, oder beinah Null macht und darauf habe ich eine Lösungsmöglichkeit gegeben.

Bis bald Chemiker
wer gesund ist hat 1000 wünsche wer krank ist nur einen.
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:13 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz