Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

05.07.2008, 01:52

Hilfe Floatvariabel kann nicht 0 werden..

Hi,

Momentan versuche ich mich wiedermal an einem Matheprogramm, bei welchem ich ein ziemliches Problem habe.

Follgende Funktion:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int CCalc::Funktion(float x)
{

  fX = x-11.1; //Das ist die Funktion F(x)


  
  
  if (fX == 0)
  {
      return  0;
  }
  else if (fX < 0)
  {
      return  1;
  }
   else if (fX > 0)
  {
      return  2;
  }



}


An die Funktion wird ein X Wert übergeben und dann soll in der Funktion überprüft werden, ob F(x) durch den übergebenen X Wert 0 wird..
Das Problem ist nun, dass die Funktion nicht 0 werden kann..Ich hab das ganze mit dem Debugger verfolgt und wenn ich an die Funktion den X Wert 11.1 übergebe dann ist die Variabel "fX" nicht wie erwartet 0 sondern bekommt den komischen Wert "2.28882e-006"

Es handelt sich bei der Variabel "fX" um eine Floatvariabel..

Würde mich über Hilfe freuen :)

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

2

05.07.2008, 02:02

1. Es heißt "Variable".
2. Hatten wir nicht schonmal so einen Thread?
3. Dort wurde dir(?) schon gesagt, dass man bei floats und Gleichheit vorsichtig sein sollte. Zahlen wie 11.1 können z.B. überhaupt nicht dargestellt werden (so wie wir 1/3 nicht als endlich langen Dezimalbruch schreiben können). Also musst du auf einen gewissen Bereich um die Null herum testen.

3

05.07.2008, 12:41

Zitat

sondern bekommt den komischen Wert "2.28882e-006"


Das ist nicht komisch, sondern eine wissenschaftliche (scientific) Notation und liest sich:

2.28882 x 10 hoch -6 oder 2.28882 : 100000

Dieses ist ein sehr kleiner Wert -> annähernd Null (0).

Am besten schreibst du dir für die Zukunft eine kleine Funktion, welche die annähernde Gleichheit von Fließkommazahlen ermittelt:

C-/C++-Quelltext

1
bool equals(double, double); // Prototyp


Folgendes muss die Funktion erfüllen:

Quellcode

1
Wenn der Absolutwert der Differenz der beiden übergebenen (double)Werte kleiner oder gleich einem bestimmten Schwellenwert (epsilon) ist, gebe 'true' zurück, andernfalls 'false'.


Einsetzen kannst du diese dann folgendermaßen:

C-/C++-Quelltext

1
2
3
4
5
// ...

if ( equals(fX, 0.0) )
  {
      return  0;
  }


Grüße... Heiko

4

05.07.2008, 15:41

Hiho,

Sorry das ich die Frage quasi doppelt gestellt habe aber ich habe völlig aus dem Augen verloren, dass ich die Frage schon gestellt hatte, weil ich die Arbeiten an diesem Projekt erstmal unterbrochen hatte.

Ich hab jetzt eine Lösung gefunden:

C-/C++-Quelltext

1
2
3
4
  if (fX  >= -0.00000001 && fX <= 0.00000001)
  {
      //Wird als 0 gewertet

  }


Das müsste doch so genau genug sein oder?

Diese Funktion mit "equals" macht auch einen recht interesanten Eindruck.
Aber funktioniert, dies denn? Es handelt sich doch um eine einfache Funktion, die einfach nur den Namen equals hat und 2 Double Variablen übergeben bekommt oder irre ich mich da?

grek40

Alter Hase

Beiträge: 1 491

Wohnort: Dresden

  • Private Nachricht senden

5

05.07.2008, 15:45

Du hast einfach übersehen, dass bwbg dir nur den Prototyp und ne Anforderungsbeschreibung gegeben hat... implementieren musste das Teil dann schon selbst ;)

6

05.07.2008, 15:57

Zitat von »"grek40"«

Du hast einfach übersehen, dass bwbg dir nur den Prototyp und ne Anforderungsbeschreibung gegeben hat... implementieren musste das Teil dann schon selbst ;)


Okey also im Prinzip hat er das selbe Vorgehen wie hier Vorgeschlagen:

C-/C++-Quelltext

1
2
3
4
if (fX  >= -0.00000001 && fX <= 0.00000001)
  {
      //Wird als 0 gewertet

  }

7

05.07.2008, 16:01

Genau, du packst deine Lösung einfach in eine Funktion, damit du sie von überall bequem benutzen kannst.
Lieber dumm fragen, als dumm bleiben!

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

8

05.07.2008, 18:09

Jo, die Idee is dir richtige. Allerdings gibts für den Epsilonwert schon eine definition:

C-/C++-Quelltext

1
2
3
4
static inline bool IsZero( const float x )
{
  return fabsf( x ) < FLT_EPSILON;
}
@D13_Dreinig

9

07.07.2008, 10:57

Nein, so ist FLT_EPSILON nicht definiert, es ist auch nicht das, was hier gewollt ist. Es ist nur die kleinste Zahl, fuer die gilt: 1.0+FLT_EPSILON != 1.0 (1.192092896e-07). Ich wuerde eine eigenes Epsilon verwenden. Leider wird der Wert von Epsilon sich an der Groesse der verwendeten Zahlen anpassen muessen.

Anonymous

unregistriert

10

07.07.2008, 11:38

Ich finde diese Lösung hier persönlich viel schöner ;)

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
#include <limits>
#include <cmath>

// [...]


template<typename T> inline bool is_zero (const T& value)
{
    return (std::abs (value) < std::numeric_limits<T>::epsilon ());
}
ggf. kann man ja auch eine Template-Spezialisierung durchführen. :)

Werbeanzeige