![]() |
floats auf Null prüfen (C++)
Ich denke mal das ist ein eher verbreitetes Problem, eine Gleitkommazahl auf Null zu prüfen. Allerdings gibt es ja nicht >die< Null wie bei Integers also gestaltet sich das etwas schwieriger.
Mit x == 0.0 gehts jedenfalls nicht, und die Null als doch recht kleines Intervall (z.B. [-0.000001|0.000001]) zu interpretieren ist auch nicht sonderlich sinnvoll :D Wie stell ich das an, außer etwas damit zu berechnen (1.0/x oder so) und zu gucken ob -1.#IND rauskommt? Eventuell Kann man das Ergebnis mit 1.0 ja noch darstellen, mit 100.0 aber nicht mehr. Exceptions werden nicht geworfen und ich möchte sie eigentlich auch vermeiden, es geht doch ein bisschen um Performance^^ cout gibt mir diese Nullen als '0' und nicht 1.0e-308 oder so, also muss es ja eine Möglichkeit geben. |
Re: floats auf Null prüfen (C++)
RoundTo Routine
Rounds a floating-point value to a specified digit or power of ten using "Banker's rounding". Unit Math Syntax [Delphi] function RoundTo(const AValue: Double; const ADigit: TRoundToRange): Double; Description Call RoundTo to round AValue to a specified power of ten. AValue is the value to round. ADigit indicates the power of ten to which you want AValue rounded. It can be any value from –37 to 37 (inclusive). RoundTo uses "Banker's Rounding" to determine how to round values that are exactly midway between the two values that have the desired number of significant digits. This method rounds to an even number in the case that AValue is not nearer to either value. The following examples illustrate the use of RoundTo: Expression Value RoundTo(1234567, 3) 1234000 RoundTo(1.234, -2) 1.23 RoundTo(1.235, -2) 1.24 RoundTo(1.245, -2) 1.24 SimpleRoundTo Routine Rounds a floating-point value to a specified digit or power of ten using asymmetric arithmetic rounding. Unit Math Syntax [Delphi] function SimpleRoundTo(const AValue: Double; const ADigit: TRoundToRange): Double; Description Call SimpleRoundTo to round AValue to a specified power of ten. AValue is the value to round. ADigit indicates the power of ten to which you want AValue rounded. It can be any value from –37 to 37 (inclusive). SimpleRoundTo uses asymmetric arithmetic rounding to determine how to round values that are exactly midway between the two values that have the desired number of significant digits. This method always rounds to the larger value. The following examples illustrate the use of SimpleRoundTo: Expression Value SimpleRoundTo(1234567, 3) 1234000 SimpleRoundTo(1.234, -2) 1.23 SimpleRoundTo(1.235, -2) 1.24 SimpleRoundTo(-1.235, -2) -1.23 Related Information Math.RoundTo |
Re: floats auf Null prüfen (C++)
@busybyte: Und was nützen einem diese Delphi Funktionen in C++?
Wenn er den C++Builder nutzen würde, dann könnte er direkt die Funktion ![]() |
Re: floats auf Null prüfen (C++)
@Muetze1
ok wenn er das für c++ haben will,dann ist wohl ein c++ Forum erfolgversprechender. :wiejetzt: andere Baustelle wenn er genau 0 haben will kann er auch IsZero verwenden,wollte es halt flexibel halten. |
Re: floats auf Null prüfen (C++)
Ich glaube, auf Intervall prüfen ist die beste Möglichkeit - was anderes außer die Stellen, die durch Konvertierungsfehler ungenau werden könnten, zu ignorieren gibts in meinen Augen nicht. ;)
Ein
Code:
dürfte dabei auch performant eine akzeptable Lösung sein.
(abs(x) < e)
[Edit]Man darf hier auch gerne C-Fragen stellen. Schließlich ist eine entsprechende Personality auch im BDS enthalten ;) @busbyte: Du kannst auch gerne einfach eine ![]() greetz Mike |
Re: floats auf Null prüfen (C++)
@busybyte: Damit hätte ich ja eine Null die von -0.5 bis 0.5 geht, das ist doch ein bisschen groß :D
Runden kann ich schon :D Und ob es jetz um C++ oder um Delphi geht ist doch egal, das Problem hat man in jeder Sprache wo man floats benutzen kann. @JasonDX: Jo dann werd ich das so machen, nur den Funktionssprung von abs kann ich mir noch sparen. Entweder (x<e || x>-e) oder ((x&0x7FFFFFFF)<e). Bleibt nur die Frage welches da jetzt schneller ist :D Auf Delphi, zum nachvollziehen: ((x<e) or (x<-e)) und ((x and $7FFFFFFF) < e) |
Re: floats auf Null prüfen (C++)
@snuffmaster dann schreib es doch in Hebräisch oder Russisch bzw. assembler wenn dir die sprache egal ist und
Gratulation das Du schon runden kannst, suchen scheint ja nicht Deine Stärke zu sein. Off |
Re: floats auf Null prüfen (C++)
Hey busybyte,
Zitat:
|
Re: floats auf Null prüfen (C++)
Zitat:
![]()
Code:
Für vorzeichenbehaftete Integerwerte funktioniert deine Vergleichsmethode übrigens auch nicht, da diese anders dargestellt werden, als du annimmst; hier am Beispiel einer 1-Byte-Zahl:
inline bool isNull (float val, float e = 0.00001f)
{ *reinterpret_cast <int*> (&val) &= 0x7FFFFFFF; return (val < e); } inline bool isNull (double val, double e = 0.000000001) { *reinterpret_cast <long long*> (&val) &= 0x7FFFFFFFFFFFFFFFul; return (val < e); } ![]() Aus diesem Grund ist ~0 (der unäre Operator ~ in C negiert den Parameter bitweise) gleichwertig mit -1, unabhängig davon, wie breit der Datentyp ist. |
Re: floats auf Null prüfen (C++)
Hallo SnuffMaster23,
mit [C++]
Code:
kann man Prüfen ob die Gleitkommazahl den Wert Null oder beinahe Null hat.
bool IsZero (long double A, long double Epsilon);
Bis bald Chemiker |
Re: floats auf Null prüfen (C++)
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; |
Re: floats auf Null prüfen (C++)
@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:
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.
#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; }
Code:
@Chemiker: Wo ist IsZero drin? Die hab ich nicht gefunden, auch nicht beim fix googeln.
Plx auf Echtzeit schalten und Taster dr³cken...
(x<e || x>-e): 0.999548 Sek. isNull: 0.999548 Sek. 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 |
Re: floats auf Null prüfen (C++)
Zitat:
|
Re: floats auf Null prüfen (C++)
Unit Math
bei Delphi for Win32 |
Re: floats auf Null prüfen (C++)
Zitat:
|
Re: floats auf Null prüfen (C++)
Zitat:
Edit: siehe unten |
Re: floats auf Null prüfen (C++)
@#15
folglich Maschinensprache=Assembler =Rad neu erfinden, jetzt bin ich aber wirklich raus aus diesem Thread |
Re: floats auf Null prüfen (C++)
Zitat:
|
Re: floats auf Null prüfen (C++)
Ein paar Dinge muß ich noch ergänzen:
Zitat:
|
Re: floats auf Null prüfen (C++)
Hallo,
@Mutetze1: Zitat:
Bis bald Chemiker |
Re: floats auf Null prüfen (C++)
Sollte das nicht x<e && x>-e heißen? Wenn eines erfüllt ist, heißt das doch nicht, dass die Zahl nahe Null ist.
|
Re: floats auf Null prüfen (C++)
Zitat:
Somit verändern sich die Meßergebnisse auch ein wenig: BCB6: (x<e && x>-e): 11.525 s isNull: 22.651 s VC2008: (x<e && x>-e): 7.492 s isNull: 20.045 s Meine Aussagen zur Interpretation der Ergebnisse scheinen aber nach wie vor zuzutreffen. |
Re: floats auf Null prüfen (C++)
Hallo DMW,
bei mir führt das aber zu falschen Ergebnissen.
Code:
Wenn ich mit x<e && x>-e den Vergleich in diesem Beispiel durchführe, so ergibt der Vergleich ungleich bei gleichen Zahlen.
#define EPSILON 0.0000000000000001 // Genauigkeit
#pragma argsused int main(int argc, char* argv[]) { double zahl1, zahl2; zahl1= 4.072300000000000; zahl2= 4.072300000000000; //1 if ((((zahl2 - EPSILON) < zahl1) && (zahl1 < (zahl2 + EPSILON)))) printf("Die Werte sind Gleich\n"); else printf("Die Werte sind ungleich!! "); //--------------------------------------------------------------------------- if ((zahl1<EPSILON) && (zahl2>-EPSILON)) printf("Die Werte sind Gleich\n"); else printf("Die Werte sind ungleich!! "); getch(); return 0; Bis bald Chemiker |
Re: floats auf Null prüfen (C++)
uiuiui, da habt ihr beide Recht mit den Fehlern :oops:
Also ich habs mit MinGW im Release Mode (code::blocks) gebaut. Hier die 'richtigen' Werte:
Code:
Also trotzdem ein unwesentlicher Unterschied.
(x<e && x>-e): 1.35776 Sek.
isNull: 1.35791 Sek. Zitat:
Das x sollte eine Art Null und nicht eine Art 4 sein. Wir versuchen ja kein a == b zu machen, sondern ein x == 0 ;) |
Re: floats auf Null prüfen (C++)
Zitat:
x < ε ^ x > -ε ist ja eine Überprüfung auf Null, nicht ein Vergleich zweier Zahlen. Um damit zwei Zahlen vergleichen zu können, bildet man die Differenz. Und mit ein wenig Mathematik kommt man dann auf das, was du im ersten Teil des Programmes benutzt: x := b - a => b - a < ε ^ b - a > -ε <=> b - ε < a ^ a < b + ε Wie du aber auf a < ε ^ b > -ε kommst, kann ich nicht nachvollziehen. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:29 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz