Hallo Forumsleser, ich programmiere schon seit einiger Zeit in C, bin aber nicht der Crack und bin nun einem Programmierproblem auf der Spur. gegeben sei folgendes Beispiel: byte GanzzahligerWert; GanzzahligerWert = 100/(1+a/b); wobei a und b Werte zwischen 1 und 50 annehmen kann. Ich vermute, dass zunächst der Klammerausdruck berechnet wird. Im Falle von a=1 und b=50 wären das GanzzahligerWert = 100/(1+1/50); Kann es sein, dass der Klammerausdruck als Integer berechet wird und deshalb (1+1/50)=1 ist und deshalb GanzzahligerWert = 100/(1+1/50); den Wert von 100 und nicht wie im Taschenrechner 98 hat? Ich habe ein bißchen recherchiert, bin aber auf keine klare Bezeichnung des Verhaltens gestoßen: implizite Typkonvertierung? Wie nennt sich das? Besten Dank für Feedback newbie12
newbie12 schrieb: > Kann es sein, dass der Klammerausdruck als Integer berechet wird und > deshalb (1+1/50)=1 ist Ja, welche Datentypen habe a und b? Wenn es keine float/double sind, führt der Compiler automatisch eine Ganzzahl Division aus. Wenn es Integer sind, kannst du einen der beiden nach float/double casten um den Compiler zu einer fließkomma Division zu zwingen.
:
Bearbeitet durch User
newbie12 schrieb: > Sorry hatte ich vergessen a und b sind ebenfalls byte. Ich vermute mal dass das eine 8bit breite Ganzzahl ist, dann würde es das beschriebene Verhalten erklären.
Max H. schrieb: > newbie12 schrieb: >> Sorry hatte ich vergessen a und b sind ebenfalls byte. > Ich vermute mal dass das eine 8bit breite Ganzzahl ist, dann würde es > das beschriebene Verhalten erklären. ..ja, genau, byte hat einen Wertebereich von 0..255. newbie12
Alternativ könntest du b*100/(a+b) rechnen. Dann gibts die Division erst ganz am Ende und es kommt zumindest irgendwas anderes als 100 raus. Bei deinem Beispiel mit a = 1 und b = 50 kommt bei mir auch nicht 98 raus sondern 98.03921569... Wenn du es als b*100/(a+b) hinschreibst kriegst du immer den abgerunderen ganzzahligen Wert den der Taschenrechner anzeigt (angenommen die Zwischenergebnisse werden nicht zu groß für int).
:
Bearbeitet durch User
empfehlung: lies ein gutes Buch oder ein gutes Online-Tutorial und arbeite solche Dingen durch. Wenn man in C programmieren will, dann sollte man wissen was implizit hinter jeder Operation passiert. Dann treten genau solche einfachen und leicht zu vermeidbaren Fehler überhaupt nicht auf.
newbie12 schrieb: > Ich habe ein bißchen recherchiert, bin aber auf keine klare Bezeichnung > des Verhaltens gestoßen: implizite Typkonvertierung? Wie nennt sich das? Das nennt sich Rechnen mit Ganzzahlen. Es wird dort gar nichts konvertiert (außer vielleicht Integer Promotion weil du sagtest, dass du mit Bytes rechntest. Wenn du mit Werten kleiner als int rechnest wird das implizit zu einem int hochkonvertiert). Implizite Konvertierung gibt es wenn die Operanden unterschiedliche Typen haben. Also z.B. ein float und ein int. Dann wird implizit zu einem float konvertiert und man kann einfach sowas wie 1.f/a schreiben wenn a ein int ist.
:
Bearbeitet durch User
ffff schrieb: > empfehlung: lies ein gutes Buch oder ein gutes Online-Tutorial und > arbeite solche Dingen durch. Wenn man in C programmieren will, dann > sollte man wissen was implizit hinter jeder Operation passiert. > > Dann treten genau solche einfachen und leicht zu vermeidbaren Fehler > überhaupt nicht auf. @all: Danke erstmal an alle für die Überlegungen. @ Sebastian V. O.: Das mit dem Umformen habe ich auch gemacht. Tatsächlich ändert sich das Ergebnis, wenn ich es so umforme, wie du vorgeschlagen hast. @ffff: So ein C-Tutorial/Buch ist groß. Ziel meiner Frage war, das beschriebene Verhalten einer Begrifflichkeit zuzuordnen, die man im Tutorial gezielt suchen kann. Es geht um die Reihenfolge der Abarbeitung eine Kette von arithmetischen Operationen bei gleichzeitiger Beschränkung des Wertebereiches. Sebastian V. O. hat es gut herausgearbeitet: GanzzahligerWert = 100/(1+a/b) und GanzzahligerWert = 100*b/(b+a) führen zu verschiedenen Ergebnissen. Vermutlich ist es so einfach, wie Sebastian V. O. es bereits gesagt hat: "Das nennt sich Rechnen mit Ganzzahlen". Ich vermute mal, dass das für jeden (längeren) arithmetischen Ausdruck gilt: jeder Wert, der sich aus zwei Operanden und einem Operator ergibt, hat den gleichen Wertebereich, wie die Variable, der am Schluß zugewiesen wird. Ich habe verstanden. Hoffentlich auch mein Compiler. Dank und guten Abend newbie12
newbie12 schrieb: > Ich vermute mal, dass das für jeden (längeren) > arithmetischen Ausdruck gilt: jeder Wert, der sich aus zwei Operanden > und einem Operator ergibt, hat den gleichen Wertebereich, wie die > Variable, der am Schluß zugewiesen wird. Nein der Typ aus zwei Operanden mit Operator ergibt sich aus den Typen der Operanden. Wenn die Typen unterschiedlich sind wird der Typ mit dem "größeren" Wertebereich gewählt. Also bei einem int und long ist der neue Typ ein long. Bei int und float gibts einen float. Wenn der arithmetische Ausdruck fertig berechnet ist gibts noch eine implizite Konvertierung zu dem Typ der Variable, welchem der Wert zugewiesen wird. Das hier sieht nach einer einigermaßen ausführlichen Beschreibung aus: http://openbook.rheinwerk-verlag.de/c_von_a_bis_z/007_c_typumwandlung_001.htm
:
Bearbeitet durch User
Sebastian V. O. schrieb: > newbie12 schrieb: >> Ich vermute mal, dass das für jeden (längeren) >> arithmetischen Ausdruck gilt: jeder Wert, der sich aus zwei Operanden >> und einem Operator ergibt, hat den gleichen Wertebereich, wie die >> Variable, der am Schluß zugewiesen wird. > > Nein der Typ aus zwei Operanden mit Operator ergibt sich aus den Typen > der Operanden. Wenn die Typen unterschiedlich sind wird der Typ mit dem > "größeren" Wertebereich gewählt. Also bei einem int und long ist der > neue Typ ein long. Bei int und float gibts einen float. Wenn der > arithmetische Ausdruck fertig berechnet ist gibts noch eine implizite > Konvertierung zu dem Typ der Variable, welchem der Wert zugewiesen wird. > > Das hier sieht nach einer einigermaßen ausführlichen Beschreibung aus: > http://openbook.rheinwerk-verlag.de/c_von_a_bis_z/007_c_typumwandlung_001.htm besten Dank, auch für den Buchtipp und die Kategorie "Typumwandlung". Newbie12
newbie12 schrieb: > hat den gleichen Wertebereich, wie die > Variable, der am Schluß zugewiesen wird. Nein. Das ist ein beliebter Fehler, der oft für Verwrrung sorgt. Dafür ist nur die rechte Seite vom = wichtig. Bei der Berechnung gelten die normalen Regeln wie Klammerung, Punkt vor Strich, ... Und es wird nur die für die jeweilige Operation notwendige Umwandlung gemacht. Bei 1.5 + 1/2 kommt 1.5 raus (double), da erstmal 1/2 als Integerdivison berechnet wird.
python2 rechnet ganzzahl wenn keine floats drinne python3 rechnet einfach so float wenn er meint es muss sein total verwirrend und absolut off topic :)
>empfehlung: lies ein gutes Buch oder ein gutes Online-Tutorial und >arbeite solche Dingen durch. Wenn man in C programmieren will, dann >sollte man wissen was implizit hinter jeder Operation passiert. >Dann treten genau solche einfachen und leicht zu vermeidbaren Fehler >überhaupt nicht auf. Super konstruktiver Vorschlag. In der Zeit hättest Du die Lösung präsentieren können :-( Warum nimmst Du nicht float als Datentyp für a und b? Rosa
Rosa schrieb: > Super konstruktiver Vorschlag. Der Vorschlag ist konstruktiv. Selbst lernen. Nicht eine Antwort vorbeten lassen, ohne zu verstehen. Aber das ist in der Generation facebook/google offensichtlich nicht zu vermitteln. > Warum nimmst Du nicht float als Datentyp für a und b? Versuch mal darüber nachzudenken, was das bedeutet. Wie heißt diese Webseite hier? "mikrocontroller.net". Und welche Auswirkung kann die Verwendung von float auf einem Mikrocontroller haben? Na?
Es ist doch auch eine Frage, ob auf Seiten der Anwendung etwas dagegen spricht. Mehr habe ich nicht gefragt. Ich glaube, du hast meine Antwort persönlich genommen. Entschuldige bitte, das kommt nicht wieder vor. Rosa Ps: ich glaube schon zu wissen, was es bedeutet, float zu nutzen. Pps:Vorführen und Nachmachen ist nicht mal die schechteste Methode, schlechter ist ein Buch, das ich nicht verstehe.
Aber einen kann ich mir jetzt nicht verkneifen: Rufus T. Firefly! Der Name ist der Hammer. Was bedeuttet das T? Take it easy :-) Rosa
python schrieb: > python2 rechnet ganzzahl wenn keine floats drinne > python3 rechnet einfach so float wenn er meint es muss sein > > total verwirrend und absolut off topic :) Verwirrend in Python 2 ist wie auch in C vor allem die Tatsache, dass der /-Operator je nach Argumenttypen für zwei völlig unterschiedliche Operationen steht. Denn die ganzzahlige Division ist im mathematischen Sinn gar keine Division, da sie nicht als Umkehrung der Multiplikation definiert ist. Während in C diese Dimorphie lediglich ein Stolperstein für Anfänger darstellt, ist sie in Python 2 eine generelle Fehlerquelle. Deswegen liefert / in Python 3 auch für Integer-Argumente ein Float-Ergebnis mit den entsprechenden Nachkommastellen. Für die ganzzahlige Division gibt es den Operator //. Evtl. wäre es auch bei der Sprachdefinition von C klüger gewesen, zwei verschiedene Operatoren für die beiden Divisionsarten vorzusehen. Womit wir auch schon fast wieder ontopic wären ;-)
Yalu X. schrieb: > Evtl. wäre es auch bei der Sprachdefinition von C klüger gewesen, zwei > verschiedene Operatoren für die beiden Divisionsarten vorzusehen. > > Womit wir auch schon fast wieder ontopic wären ;-) Und noch etwas mehr Off-Topic: Da würden Mathematiker wohl etwas dagegen haben... Das, was C da macht, ist ganz normale Arithmetik über einem Restklassenring bzw. Faktorring und hat den schönen Nebeneffekt, dass bspw., falls das multiplikate Inverse existiert, eine Division durch eine Multiplikation mit dem Inversen berechnet werden kann.
Arc Net schrieb: > Da würden Mathematiker wohl etwas dagegen haben... Ich bin zwar selber kein Mathematiker, könnte mir aber vorstellen, dass gerade Mathematiker eine klarere Unterscheidung zwischen der echten und der ganzzahligen Division befürworten würden. Gerade in den funktionalen Programmiersprachen, die prinzipiell etwas mathematischer angehaucht sind als andere, wird diese Unterscheidung praktisch immer gepflegt. > Das, was C da macht, ist ganz normale Arithmetik über einem > Restklassenring bzw. Faktorring und hat den schönen Nebeneffekt, dass > bspw., falls das multiplikate Inverse existiert, eine Division durch > eine Multiplikation mit dem Inversen berechnet werden kann. Solche Späße wären aber doch auch möglich, wenn der Operator für die ganzzahlige Division ander als / heißen würde, oder?
python schrieb: > python3 rechnet einfach so float wenn er meint es muss sein Was natürlich Unsinn ist. Python 3 ist sehr viel konsistenter als Python 2, was das Divisionsverhalten angeht. Siehe / vs. //
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.