Abfrage nach ganzer Zahl in C

  • #1
C

cateye

Bekanntes Mitglied
Themenersteller
Dabei seit
24.12.2001
Beiträge
296
Reaktionspunkte
0
Ort
Magdeburg
Hi,

wie kann ich in einem C-Programm abfragen, ob eine in eingegebene Float-Variable ganzzahlig ist, also sodass auch Zahlen wie 1,000001 als float erkannt werden und erst bei wirklich nur Nullen hinterm Komma als ganzzahlig. Die Zahl soll der Zelle eines Feldes zur Überprüfung entnommen werden.

CU

Cateye
 
  • #2
Kennt C keinen int Befehl?
if Zahl = int(Zahl) then
Setz das in C um, das müsste funktionieren.

Eddie
 
  • #3
So wie Eddie es vorschlägt oder

float b = a - floor(a);
if(b > 0.0f)
  ...

Natürlich setzt die Genauigkeit des Typs Grenzen (egal, welche Methode Du verwendest); z.B. klappt es bei 100.000001 nicht mehr, da dies 100 entspricht. Allerdings dürfte in der Box auch nicht 100.000001 stehen, wenn die interne Repräsentation vom Typ float ist.
 
  • #4
Hi,

ich hab's jetzt mal so versucht:

#include <stdio.h>

int main()
{
float a;

printf (Wert für a eingeben: );
scanf (%f,&a);
if (a==int(a))
printf (\nInhalt von a ist %f,a);
else
printf (\n a ist kein Integer);

return 0;
}

weil ich ja zwei = brauche, damit es ein Vergleich und keine Wertzuweisung ist, aber mein Compiler meldet einen ParseError vor int, also geht es so scheinbar nicht.

Ich kriege in einer Funktion meines Programms aber auch eine Speicherzugriffsverletzung, wenn ich Werte einlesen will (siehe FEHLER =>):

# include <stdio.h>
# define g 10

float read(float f[g][g+1],int a)
{
int z,s;

printf (\nType in the values of your %d equations as follows:\n,a);

for (z=0;z<a;z++)
{
printf (\n%d: A*X+B*Y+....+N=0 (press q to abort)\n,z+1);
for (s=0;s<a-1;s++)
{
printf (\nValue %c for %d. equation: ,65+s,z+1); // 65=ASCII-Code für A
FEHLER => scanf (%f,f[z]);
if (f[z]=='q')
{
printf (program aborted!!!);
return 0;
}
}
printf (\nValue N for %d. equation:,z+1); //Extraaufruf, weil Absolutglied-Buchstabe
scanf (%f,f[z][s+1]);
if (f[z][s+1]=='q')
{
printf (program aborted!!!);
return 0;
}
}
return 0;
}

Die zugehörigen Zeilen zum Aufrufen der Funktion in Main sind folgende:

int main ()
{
float f[g][g+1],c[2][g+1],a=0;
int n,i,e=-1;

printf (\nNumber of Unknowns (<=%d):,g);
scanf (%d,&n);
if (n>g||n<=0)
{
printf (\nWrong input, program aborted!!!\n\n);
return 0;
}
read(f,n);
.....
}

Der Durchlauf des Programms bis zum Abbruch sieht ungefähr so aus:

EXECUTING:
/home/cateye/programming/Gleichung
----------------------------------------------

Number of Unknowns (<=10):2

Type in the values of your 2 equations as follows:

1: A*X+B*Y+....+N=0 (press q to abort)

Value A for 1. equation: 2

----------------------------------------------
Program has been terminated receiving signal 11 (Segmentation fault)
Press the Enter key to close this terminal ...

Ich kann aber keine logischen Fehler feststellen und der Compiler läuft auch durch (unter Windoze wird nichtmal der Quelltext gefunden, obwohl ich die Datei durch Rechtsklick über den Compiler geöffnet, bearbeitet und unter neuem Namen gespeichert habe :p) Das Feld wird der Funktion genau in den Abmessungen übergeben, in der die Funktion es nehmen soll und die Beschränkung der Bearbeitung auf einzelne Bereiche des Feldes erfolgt innerhalb der Funktion selbst. Nur wenn ich an der markierten Stelle in der Funktion angekommen bin, kommt der Fehler Segmentation Fault, also Speicherzugriffsverletung. Ich hab auch schon versucht, die Variable g an den entsprechenden Stellen direkt durch die 10 zu ersetzen, aber das bringt auch nichts. Habt ihr irgendwelche Ideen?
 
  • #5
weil ich ja zwei = brauche, damit es ein Vergleich und keine Wertzuweisung ist, aber mein Compiler meldet einen ParseError vor int, also geht es so scheinbar nicht.

Eddie schrieb:
Setz das in C um, das müsste funktionieren.

In C must Du casten (-> (int)a)). Dabei wird alles nach dem Komma abgeschnitten. Oder Du bindest math.h ein und benutzt die Funktion floor (s.o.).

Code:
scanf (%f, f[z][s]);

scanf erwartet Adressen von Parameter 2 bis n.

Code:
scanf (%f, &f[z][s]);

BTW: Das hier geht nicht:
Code:
if (f[z][s]=='q')

Im Array stehen binäre float-Werte; die kannst Du nicht mit einem Zeichen vergleichen. D.h., Du kannst schon, aber es kommt nix Sinnvolles dabei raus ;).

Die Zahl soll der Zelle eines Feldes

Das mit der Zelle hatte ich falsch verstanden; ich dachte, die Eingabe erfolgt über eine Textbox / eine Tabelle o.ä. Die Sache mit der Genauigkeit gilt natürlich trotzdem: 100.000001 als float = 100: 100.000001 - 100 = 0.
 
  • #6
Hi,

danke für die ausführliche Antwort. Bei scanf bin ich davon ausgegangen, dass bei Feldern automatisch die Adressen benutzt werden, wie es in Funktionen ja normalerweise der Fall ist, aber ich übergebe ja hier nicht das ganze Feld, sondern nur 1 Element :| ::)
Was das Grundproblem, also die Abfrage der Float-Variablen nach ganzer Zahl angeht, hilft mir das Kastrieren um die Komma-Stellen nicht wirklich weiter. Das Programm oben soll dazu dienen, lineare Gleichungssysteme mit maximal 10 Unbekannten (falls einer so viel Langeweile hat das einzutippen :p) zu lösen. Das soll mit dem Pivot-Verfahren geschehen, d.h. von der ersten Gleichung wird die erste Zahl genommen (=Pivot-Element) und diese fungiert bei den folgenden Divisionen/Brüchen im Nenner, ist also die Zahl durch die geteilt wird. Aus Gründen der Genauigkeit wollte ich die eingegebenen ersten Elemente der jeweiligen Gleichungen darauf überprüfen, ob sie ganzzahlig sind, da eine Division durch eine ganze Zahl weniger Rundungsfehler mit sich bringt. Eine Gleichung mit ganzzahligem ersten Element würde ich dann einfach mit der ersten Gleichung austauschen. Meine Funktion dazu sieht folgendermaßen aus:

float change(float f[g][g+1],int a)
{
float b;
int s;

for (s=0;s<g+1;s++) //Zeilenindex konstant, Spalten der Reihe nach ausgetauscht
{
f[0]=b;
f[a]=f[0];
f[a]=b;
}
return 0;
}

Außerdem überprüfe ich die ersten Elemente auf Werte von 1 bzw. 0 in main():

for (i=0;i<n;i++) //n ist die am Anfang eingelesene Anzahl der Gleichungen
{
if (f[0]==1)
{
e=i;
break;
}
}
if (e=!-1) // e wurde am Anfang von main() mit -1 initialisiert, da -1 als Feldindex nicht vorkommt
change (f,e);

e=-1;

if (f[0][0]==0) //Pivot-element different from 0
{
for (i=1;i<n;i++)
{
if (f[0]=!0)
{
e=i;
break;
}
}
if (e=!-1)
change (f,e);
if (e==-1)
{
printf (\nWrong amount of equations chosen at the beginning);
printf (\nProgram aborted!!!);
}
}

Nur die Prüfung auf eine beliebige ganze Zahl, die ich dann sinnvollerweise (mit if (f[0][0]=!1)-Abfrage) zwischen beide Abschnitte legen würde, fehlt mir noch. :-\
Ich hab mir überlegt, die jeweils erste Zahl der Gleichung in ein Extra-Feld einzutragen, wobei jede Stelle dieser Zahl und das Komma in jeweils ein Element des Feldes eingetragen wird. Dann könnte man die Stellen bis zum Komma einfach mit einer ASCII-Abfrage (Komma=44) überspringen und die Stellen danach über == bzw. =! auswerten, aber ich hab keine Ahnung, wie ich die einzelnen Stellen einer Float-Variable in das Feld kriege. Hast du ne Idee?
 
  • #7
Code:
float change(float f[g][g+1],int a)
{
  float b;
  int s;

  for (s=0;s<g+1;s++)    //Zeilenindex konstant, Spalten der Reihe nach ausgetauscht
  {
    // Nach den 3 Zeilen sind f[0][s] und f[a][s] undefiniert

    f[0][s]=b;
    f[a][s]=f[0][s];   
    f[a][s]=b;
  }
  return 0;
}

Code:
void swap(float f[][g+1], int a)
{
  float b;
  int s;

  for (s=0; s<g+1; s++)    // Zeilenindex konstant, Spalten der Reihe nach ausgetauscht
  {
    b= f[0][s];
    f[0][s] = f[a][s];
    f[a][s]= b;
  }
}

BTW: Warum verwendest Du nicht wenigstens double, wenn es Dir um Genauigkeit geht?

Zu der Prüfung auf ganze Zahlen: Wir reden da aneinander vorbei, glaube ich :). Wenn Du mit den genannten Methoden zum Ergebnis kommst, dass es sich um eine ganze Zahl handelt, hast Du eine ganze Zahl; was der Anwender da irgendwo weit hinter dem Komma eingegeben hat (2,000000000000000000001) spielt gar keine Rolle für Dich, da Du dies mit einem float nicht erfassen kannst. Das ist im gegebenen Kontext gleich 2; die genannten Methoden liefern Dir auch korrekterweise die Information, dass es sich um eine ganze Zahl handelt.
Auch eine Analyse und Umwandlung eines Eingabe-Strings von Hand (die natürlich möglich ist: String einlesen und in einer Schleife Zeichen für Zeichen auswerten) bringt Dich nicht weiter. Damit bekommst Du heraus, dass 2,000000000000000000001 keine ganze Zahl ist. Dies ist aber - wie gesagt, im Kontext des Programms - unwahr.
Du kannst dies dem Anwender höchstens deutlich machen, z.B. durch die Anzeige des realen Wertes nach der Eingabe.
 
  • #8
Danke für die ausführlichen Antworten ;D Den Zuweisungsfehler hatte ich auch schon entdeckt, aber es gibt so einige andere Sachen zu dem Programm (die noch rein müssten), die mir momentan noch zu hoch sind. :-\ :'( Ich glaube ich werde mich dann wohl doch erstmal mit meinem treuen kleinen Taschenrechner zufrieden geben. Der kann lineare Gleichungssysteme bis 6 Variablen lösen und wenn ich mehr habe, bestimme ich eben die übrigen Variablen auf dem guten alten Weg mit Papier und Stift. ::)

CU

Cateye
 
Thema:

Abfrage nach ganzer Zahl in C

ANGEBOTE & SPONSOREN

Statistik des Forums

Themen
113.840
Beiträge
707.965
Mitglieder
51.494
Neuestes Mitglied
Flensburg45
Oben