Rechenfehler?

Hallo, kann mir vielleicht jemand sagen, an welcher Stelle ich gerade ein wenig Blind bin?

die beiden Variablen deltaGo3u2 und deltaGu2u3 sind nach einigen Rechnungen mit den Werten 55 und 12 gefüllt. die Variable Nenner bekommt jedoch nicht den wahren Wert von -0,0106, sondern trägt als Ergebnis eine 0.

Code:
int deltaGo3u2, deltaGu2u3;
double Nenner;
...
Nenner = 4/deltaGo3u2 - 1/deltaGu2u3;

Wo ist da mein Denkfehler?
 
Du machst Integer-Divisionen, die werden auch so behandelt. Da es bei Integer keine Nachkommastellen gibt, werden diese abgeschnitten. Erst das Endergebnis wird in double umgewandelt.

Du kannst die Umwandlung aber bereits vorher erzwingen:

int deltaGo3u2, deltaGu2u3;
double Nenner;
...
Nenner = 4.0 / deltaGo3u2 - 1.0 / deltaGu2u3;

Durch das .0 werden die Zahlen als double eingesetzt, und folglich findet dann keine Integer-Division mehr statt, sondern bereits eine double-Division. Da gehen dann auch keine Nachkommastellen mehr verloren.
 
Hi,

nachdem ich das nun geändert habe, passiert folgendes:

1. beim compilieren kommt die Fehlermeldung (im debug fenster)
HC5011::Error:messsystem.hpj
Cannont open the file C:\...\VC98\MFC\include\afxhelp.hm.

wobei Messsystem mein Projekt ist,
und die Datei afxtempl.h included wurde für die Klasse CList
CList ist eine Liste, aus der bei mir die Werte für deltaGo3u2 und deltaGu2u3 stammen.

Gestartet wird mein Projekt trotzdem, stürzt aber ab, sobald die Subroutine aufgerufen wird, in der die Rechnung durchgeführt wird.

Ändere ich die 4.0 und 1.0 wieder in 4 und 1, funktioniert alles wieder wie üblich.
 
Mit Verlaub, wenn die Änderung zu einem Absturz führt, dann ist da entweder im Code hinterher ein Problem, weil der nicht mit Werten ungleich 0 klarkommt, oder der Compiler Mega-Schrott (was ich aber ausschliesse).

Die Warnung ist auf ein Zugriffsproblem bei den Dateien zurückzuführen, auch damit kann die Code-Änderung absolut nichts zu tun haben.
 
Das merkwürdige ist halt,
bei 4.0 Absturz
und bei 4 kein Absturz.

Und nach dem gezeigtem Code-Ausschnitt folgt eigentlich auch nur reine Rechnung. Daher bin ich ein wenig verwundert. Zumal die Klasse CList (auf die ja bei der Fehlermeldung hingewiesen wird) vor dem Code-Schnipsel verwendet wird.

Dachte, vielleicht kannst Du oder jemand anders etwas mit dem Fehler anfangen.
 
Kannst du denn da beim Debuggen nicht den tatsächlichen Absturzort feststellen?

Wenn das innerhalb der Routine ist, müsste sich das doch halbwegs nachstellen lassen. Kannst du den Inhalt der Routine hier posten?
 
Ok, die ganze Routine wäre ein wenig viel Code. Daher habe ich die Funktion etwas verkürzt...

Möglicherweise haben die Fehlermeldung und der Absturz zwei verschiedene Ursachen.

Die Fehlermeldung sieht so aus, als hätte sie etwas an der Klasse CList zu mäkeln.
Der Absturz allerdings wird vermieden, sobald ich auf den Aufruf von WriteLog verzichte.

Beides, sowohl die Fehlermeldung als auch der Absturz passieren aber nur, wenn in der Berechnung von Nenner eine 4.0 und eine 1.0 steht. Schreibe ich statt dessen 4 und 1, passiert nichts von beiden.

Code:
#include <afxtempl.h>	//für Klasse CList (Auflistung ohne bekannte Dimensionen)
void FindGradient(unsigned char Quelle[], unsigned char Zeichnung[], int width, int height)
{
	//Füllen der Liste KanteY
	CList<CPoint,CPoint> KanteY;
	CPoint Pixel;
...
	for (i=0; i<width; i++)
	{
	...
	KanteY.AddTail(Pixel);
	...
	}

	//Abarbeiten der Liste KanteY
	double Nenner;
	int deltaGo3u2, deltaGu2u3;
	POSITION posY = KanteY.GetHeadPosition();

	Pixel = KanteY.GetNext(posY);
	//deltaG-Werte wurden berechnet aus Pixel.x und Pixel.y
	//deltaGo3u2 = 55 und deltaGu2u3 = 12
	Nenner = (4.0/deltaGo3u2) - (1.0/deltaGu2u3);
	//WriteLog wurde von mir geschrieben, um von jedem Ort des Programms aus 
	//Daten in ein bestimmtes Textfeld schreiben zu können
	WriteLog(0, "Nenner: ", Nenner);
	...
}

Folglich habe ich die Funktion WriteLog noch angehängt.

Code:
//m_sLog ist eine Membervariable, die mit dem Textfeld verknüpft ist
//pMyDlg ist ein pointer, der auf mein Hauptdialogfenster zeigt

#include <stdlib.h>	//für Funktion _gcvt (double into string)
void WriteLog(int Format, CString First = "", double Second = NULL, CString Third = "")
{
	char sMessage[4];
	pMyDlg->UpdateData(TRUE);
	
	if (Format == 1)
	{
		CTime theTime = CTime::GetCurrentTime();
		CString Uhrzeit = theTime.Format("%H:%M:%S ");
		pMyDlg->m_sLog += Uhrzeit;
	}

	pMyDlg->m_sLog += First;

	if (Second != NULL)
	{
		_gcvt(Second,10,sMessage);
		pMyDlg->m_sLog += sMessage;
	}
	
	pMyDlg->m_sLog += Third;
	pMyDlg->m_sLog += "\r\n";
	pMyDlg->UpdateData(FALSE);
}

Hoffe, das sind genügend Informationen, dass man hier durchblicken kann :)
 
Autsch, dadurch dass ich die Routine WriteLog mehrfach verändert habe, hat sich dort wohl ein Fehler bei der Deklaration von sMessage eingeschlichen.

char sMessage[4] muss mindestens sMessage[10] sein, da in der Funktion _gcvt() auf 10 Stellen gerundet wird.

Manchmal muss man den Code halt nur ausgedruckt sehen *grml*

Aber die Fehlermeldung hab ich immernoch nicht ergründen können.
 
Zuletzt bearbeitet:
Aha, bei _gcvt muss man vorsichtig sein. Also der Fehler tritt dadurch auf, dass Second in WriteLog ungleich NULL (=0.0) wird, wenn man die 4.0 und 1.0 einsetzt.

In der MSDN steht zu _gcvt, dass die Funktion durchaus mehr Zeichen als angegeben in den Buffer schreibt. Um ganz sicher zu gehen, dass die Zahl immer reinpasst, das Define _CVTBUFSIZE als Array-Grösse verwenden:

char sMessage[_CVTBUFSIZE];
 
Zurück