Flächeninhalt bestimmen
-
Hallo SeppJ!
Auf stackoverflow habe ich dazu folgenden Kommentar gefunden:
"I don't know what they were smoking when they wrote that. Double.Epsilon is the smallest representable non-denormal floating point value that isn't 0. All you know is that, if there's a truncation error, it will always be larger than this value. Much larger."
Der Erste Teil des Kommentar bezieht sich anscheinend auf die Programmierer von MS.
-
@rustyoldguy sagte in Flächeninhalt bestimmen:
Für Leute mit gcc, welche
Kompatibilität zu Microsofts 'double Epsilon' suchen:double Epsilon(void)
Es gibt dafür extra ein Makro
#include <float.h> #include <stdio.h> #include <stdlib.h> int main () { printf ("%e\n", DBL_EPSILON); return EXIT_SUCCESS; }
Wenn man so Fragen hat sollte man sich mit dem Inhalt von
float.h
unbedingt vertraut machen.
-
So hätte ich das gemacht; hoffe, habe nix übersehen:
#include <iostream> #include <map> #include <math.h> using namespace std; enum Typ_Dreieck { gleichschenklig = 1, rechtwinklig = 2, beliebig = 0 }; class Dreieck { private: public: Dreieck(float a, float b, float c); ~Dreieck(); float a, b, c; const float e = 0.1; bool is_equal(float a, float b) const { return fabs(a - b) - e <= 0; } bool is_gleichschenklig() const { return is_equal(a, b) || is_equal(a, c) || is_equal(b, c); } bool is_rechtwinklig() const { float a2 = a * a; float b2 = b * b; float c2 = c * c; if (is_equal(a, b)) return is_equal(a2 + b2, c2); if (is_equal(a, c)) return is_equal(a2 + c2, b2); if (is_equal(b, c)) return is_equal(b2 + c2, a2); return false; } Typ_Dreieck get_type() const { if (is_rechtwinklig()) return Typ_Dreieck::rechtwinklig; if (is_gleichschenklig()) return Typ_Dreieck::gleichschenklig; return Typ_Dreieck::beliebig; } }; Dreieck::Dreieck(float a, float b, float c) : a{a}, b{b}, c{c} {}; Dreieck::~Dreieck() { } const char *type_to_string(Typ_Dreieck e) { const map<Typ_Dreieck, const char *> my_map{ {Typ_Dreieck::beliebig, "beliebig (type 0)"}, {Typ_Dreieck::gleichschenklig, "gleichschenklig (type 1)"}, {Typ_Dreieck::rechtwinklig, "rechtwinklig (type 2)"}}; auto it = my_map.find(e); return it == my_map.end() ? "Out of range" : it->second; } ostream &operator<<(ostream &strm, const Dreieck &d) { return strm << "Dreieck(" << d.a << ", " << d.b << ", " << d.c << ", " << type_to_string(d.get_type()) << ")"; } int main(int argc, char **argv) { cout << Dreieck(1.414, 1.414, 2) << endl; cout << Dreieck(1, 2, 3) << endl; cout << Dreieck(4, 4, 0.001) << endl; return EXIT_SUCCESS; }
Edit: Ach klar habe ich etwas übersehen...:
bool is_rechtwinklig() const { float a2 = a * a; float b2 = b * b; float c2 = c * c; return is_equal(a2 + b2, c2) || is_equal(a2 + c2, b2) || is_equal(b2 + c2, a2); }
int main(int argc, char **argv) { cout << Dreieck(15, 20, 25) << endl; cout << Dreieck(1.414, 1.414, 2) << endl; cout << Dreieck(1, 2, 3) << endl; cout << Dreieck(4, 4, 0.001) << endl; return EXIT_SUCCESS; }
Ersteres Dreieck wäre ohne Änderung nicht rechtwinklig gewesen...
-
Sorry, immer noch falsch.
Ein beliebiges oder gleichschenkliges Dreieck KANN rechtwinklig oder nicht rechtwinklig sein. Das eine bedingt oder schließt das andere nicht aus. Man braucht zwei enum:Typ_Schenkel_Dreieck
undTyp_Winkel_Dreieck
.
-
Das sollten jetzt alle Fälle sein...
#include <iostream> #include <map> #include <string> #include <math.h> using namespace std; enum Typ_Schenkel_Dreieck { beliebig, gleichschenklig, gleichseitig }; enum Typ_Winkel_Dreieck { spitzwinklig, stumpfwinklig, rechtwinklig }; class Dreieck { private: public: float a, b, c; const float e = 0.1; float aw, bw, cw; Dreieck(float a, float b, float c) : a{a}, b{b}, c{c} { float a2 = a * a, b2 = b * b, c2 = c * c; aw = acosf((b2 + c2 - a2) / (2 * b * c)) * (180 / 3.14159265358979323846); bw = acosf((a2 + c2 - b2) / (2 * a * c)) * (180 / 3.14159265358979323846); cw = acosf((a2 + b2 - c2) / (2 * a * b)) * (180 / 3.14159265358979323846); }; ~Dreieck() { } bool is_equal(float a, float b) const { return fabs(a - b) - e <= 0; } Typ_Schenkel_Dreieck get_type_schenkel() const { if (is_equal(a, b) && is_equal(b, c)) return Typ_Schenkel_Dreieck::gleichseitig; if (is_equal(a, b) || is_equal(a, c) || is_equal(b, c)) return Typ_Schenkel_Dreieck::gleichschenklig; return beliebig; } Typ_Winkel_Dreieck get_type_winkel() const { if (is_equal(aw, 90) || is_equal(bw, 90) || is_equal(cw, 90)) return Typ_Winkel_Dreieck::rechtwinklig; if (aw >= 90 || bw >= 90 || cw >= 90) return Typ_Winkel_Dreieck::stumpfwinklig; return Typ_Winkel_Dreieck::spitzwinklig; } }; const char *type_to_string(Typ_Schenkel_Dreieck es, Typ_Winkel_Dreieck ew) { string s1, s2; switch (es) { case Typ_Schenkel_Dreieck::beliebig: s1 = "beliebig, "; break; case Typ_Schenkel_Dreieck::gleichschenklig: s1 = "gleichschenklig, "; break; case Typ_Schenkel_Dreieck::gleichseitig: s1 = "gleichseitig, "; break; default: s1 = "not defined"; break; } switch (ew) { case Typ_Winkel_Dreieck::spitzwinklig: s2 = "spitzwinklig"; break; case Typ_Winkel_Dreieck::stumpfwinklig: s2 = "stumpfwinklig"; break; case Typ_Winkel_Dreieck::rechtwinklig: s2 = "rechtwinklig"; break; default: s2 = "not defined"; break; } return (s1 + s2).c_str(); } ostream &operator<<(ostream &strm, const Dreieck &d) { return strm << "Dreieck(" << d.a << ", " << d.b << ", " << d.c << ", " << d.aw << ", " << d.bw << ", " << d.cw << "," << endl << type_to_string(d.get_type_schenkel(), d.get_type_winkel()) << ")"; } int main(int argc, char **argv) { cout << Dreieck(15, 20, 25) << endl; cout << Dreieck(1.414, 1.414, 2) << endl; cout << Dreieck(2, 2, 3) << endl; cout << Dreieck(4, 4, 1) << endl; return EXIT_SUCCESS; }
-
@EinNutzer0 Dir ist hoffentlich aufgefallen, dass das Thema unter der Rubrik C eingestellt ist und nicht unter C++?
-
Und wegen
const char *type_to_string(...) { // ... return (s1 + s2).c_str(); }
auch noch UB (nimm also
string
als Rückgabetyp).
-
@john-0 sagte in Flächeninhalt bestimmen:
@EinNutzer0 Dir ist hoffentlich aufgefallen, dass das Thema unter der Rubrik C eingestellt ist und nicht unter C++?
Naja aber lässt sich ja, wenn er
<math.h>
inkludiert, einfach nach C übertragen - da muss er eben alles in eine Funktion schreiben.@Th69 sagte in Flächeninhalt bestimmen:
nimm also string als Rückgabetyp
Danke.
-
-
Hier einmal der C-Code:
#include <stdio.h> #include <stdlib.h> #include <math.h> typedef struct Dreieck { float a, b, c, aw, bw, cw; } Dreieck; Dreieck *get_Dreieck(float a, float b, float c) { float a2 = a * a, b2 = b * b, c2 = c * c; Dreieck *d = (Dreieck *)malloc(sizeof(Dreieck *)); d->a = a; d->b = b; d->c = c; d->aw = acos((b2 + c2 - a2) / (2 * b * c)) * (180 / 3.14159265358979323846); d->bw = acos((a2 + c2 - b2) / (2 * a * c)) * (180 / 3.14159265358979323846); d->cw = acos((a2 + b2 - c2) / (2 * a * b)) * (180 / 3.14159265358979323846); if (d->aw == 0 || d->bw == 0 || d->cw == 0) { printf("Unmögliches Dreieck angegeben!!\n"); free(d); return 0; } return d; } int is_equal(float a, float b) { return fabs(a - b) - 0.1 <= 0; } void print_Dreieck(Dreieck *d) { float s, A; if (d == 0) return; printf("Dreieck: %f %f %f %f %f %f\n", d->a, d->b, d->c, d->aw, d->bw, d->cw); if (is_equal(d->a, d->b) && is_equal(d->b, d->c)) printf("Das Dreieck ist gleichseitig\n"); else if (is_equal(d->a, d->b) || is_equal(d->a, d->c) || is_equal(d->b, d->c)) printf("Das Dreieck ist gleichschenklig\n"); else printf("Das Dreieck ist beliebig\n"); if (is_equal(d->aw, 90) || is_equal(d->bw, 90) || is_equal(d->cw, 90)) printf("Das Dreieck ist rechtwinklig\n"); else if (d->aw >= 90 || d->bw >= 90 || d->cw >= 90) printf("Das Dreieck ist stumpfwinklig\n"); else printf("Das Dreieck ist spitzwinklig\n"); s = (d->a + d->b + d->c) * 0.5; A = sqrt(s * (s - d->a) * (s - d->b) * (s - d->c)); printf("Der Flächeninhalt entspricht: %f\n\n", A); } int main() { print_Dreieck(get_Dreieck(1, 2, 3)); print_Dreieck(get_Dreieck(2, 2, 3)); print_Dreieck(get_Dreieck(15, 20, 25)); print_Dreieck(get_Dreieck(3, 3, 3)); return 0; }
Bitte mit
-lm
compilieren!!$ ./Dreieck.out Unmögliches Dreieck angegeben!! Dreieck: 2.000000 2.000000 3.000000 41.409622 41.409622 97.180756 Das Dreieck ist gleichschenklig Das Dreieck ist stumpfwinklig Der Flächeninhalt entspricht: 1.984313 Dreieck: 15.000000 20.000000 25.000000 36.869896 53.130100 90.000000 Das Dreieck ist beliebig Das Dreieck ist rechtwinklig Der Flächeninhalt entspricht: 150.000000 Dreieck: 3.000000 3.000000 3.000000 60.000000 60.000000 60.000000 Das Dreieck ist gleichseitig Das Dreieck ist spitzwinklig Der Flächeninhalt entspricht: 3.897114
Nu hab ich endlich alle Fälle abgefrühstückt,
daran, dass ein gegebenes Dreieck natürlich auch ungültig sein kann, hab ich erst wieder nicht gedacht!!
-
Du hast ein Speicherleck eingebaut.
Deine Funktion get_Dreieck erzeugt ein NEUES Dreieck, das aber nie freigegeben wird.
Und das hier:
Dreieck *d = (Dreieck *)malloc(sizeof(Dreieck *));
WTF? Der Cast ist in C nicht nötig und sizeof von einem Pointer?
-
@wob sagte in Flächeninhalt bestimmen:
Der Cast ist in C nicht nötig
Ein C/C++-Programmierer ...
@EinNutzer0 Vielleicht auch mal drüber nachdenken daß man Variablen auch auf den ersten Blick verständliche Namen geben kann ohne groß über die rechte Seite von
=
nachdenken zu müssen.
-
@Swordfish sagte in Flächeninhalt bestimmen:
WTF? Der Cast ist in C nicht nötig
ok, was WTF war mehr auf den hinteren Teil meiner Aussage bezogen. Das
malloc(pointerlänge)
für ein Dreieck. => Heap-Overflow. Der Cast ist nicht so relevant hier, wenn da so ein Klopper drin ist.
-
Ups, ja habt recht, Copy'n'Paste
-
@wob Zitat editiert ^^
-
Vielleicht noch von Interesse:
#include <stdio.h> #include <stdlib.h> #include <math.h> typedef struct Dreieck { float a, b, c, aw, bw, cw; } Dreieck; Dreieck *get_Dreieck(float a, float b, float c) { float a2 = a * a, b2 = b * b, c2 = c * c; Dreieck *d = malloc(sizeof(Dreieck)); d->a = a; d->b = b; d->c = c; d->aw = acos((b2 + c2 - a2) / (2 * b * c)) * (180 / 3.14159265358979323846); d->bw = acos((a2 + c2 - b2) / (2 * a * c)) * (180 / 3.14159265358979323846); d->cw = acos((a2 + b2 - c2) / (2 * a * b)) * (180 / 3.14159265358979323846); if (d->aw == 0 || d->bw == 0 || d->cw == 0) { printf("Unmögliches Dreieck angegeben!\n\n"); free(d); return 0; } return d; } int is_equal(float a, float b) { return fabs(a - b) - 0.1 <= 0; } void print_Dreieck(Dreieck *d) { float s, A; if (d == 0) return; printf("Dreieck: %f %f %f %f %f %f\n", d->a, d->b, d->c, d->aw, d->bw, d->cw); if (is_equal(d->a, d->b) && is_equal(d->b, d->c)) printf("Das Dreieck ist gleichseitig\n"); else if (is_equal(d->a, d->b) || is_equal(d->a, d->c) || is_equal(d->b, d->c)) printf("Das Dreieck ist gleichschenklig\n"); else printf("Das Dreieck ist beliebig\n"); if (is_equal(d->aw, 90) || is_equal(d->bw, 90) || is_equal(d->cw, 90)) printf("Das Dreieck ist rechtwinklig\n"); else if (d->aw >= 90 || d->bw >= 90 || d->cw >= 90) printf("Das Dreieck ist stumpfwinklig\n"); else printf("Das Dreieck ist spitzwinklig\n"); s = (d->a + d->b + d->c) * 0.5; A = sqrt(s * (s - d->a) * (s - d->b) * (s - d->c)); printf("Der Flächeninhalt entspricht: %f\n\n", A); } void get_and_print_Dreieck(float a, float b, float c) { Dreieck *d = get_Dreieck(a, b, c); if (d) { print_Dreieck(d); free(d); } } int main() { get_and_print_Dreieck(1, 2, 3); get_and_print_Dreieck(2, 2, 3); get_and_print_Dreieck(15, 20, 25); get_and_print_Dreieck(3, 3, 3); return 0; }
(wieder mit
-lm
compilieren)Jetzt müsste sich der Themenersteller noch einmal melden, ob er noch weitere "Sachen" im Dreieck berechnen möchte - oder, ob das so ok wäre...
Ich finde es btw nicht so schlimm, wenn die Attribute a,b,c,usw. heißen, denn bei einem Dreieck weiß man doch, dass damit die Seitenlängen gemeint sind.