float Variable gibt bei Division einen int zurück (C#)?

5 Antworten

Vom Fragesteller als hilfreich ausgezeichnet

Das liegt an der Art und Weise, wie C# intern arbeitet.

Es wird nicht erst die Variable als float deklariert und dann berechnet, sondern umgekehrt: Erst wird berechnet und danach die Variable deklariert und zugewiesen.

Das heißt, deine Berechnung sieht effektiv "int / (int * int)" und das Ergebnis davon ist auch ein int. Erst danach wird die Variable zugewiesen.

Du hast also mehrere Möglichkeiten: Mach die "difficulty"-Variable als float, oder rechne "10F" durch das Quadrad von "difficulty". Das "F" hinter der 10 sagt dem Compiler ("D" für double), dass die 10 als float betrachtet werden soll und nicht als int. Oder Du castest in der Berechnung auf float.

Immer wenn ein Teil einer Berechnung einen anderen Typ hat, als der andere Teil, versucht C# eine implizite Konvertierung. Bedenke dabei aber, dass auch die Berechnung aus mehreren Schritten bestehen kann. In deinem Fall wäre das erst die Multiplikation (da sie in Klammern steht), danach die Division. Das sind zwei Rechenschritte, für die die gleichen Regeln gelten.

Woher ich das weiß:Berufserfahrung – C#.NET Senior Softwareentwickler
GuteAntwort2021  31.12.2023, 16:28
oder rechne "10F" durch das Quadrad von "difficulty". Das "F" hinter der 10 sagt dem Compiler ("D" für double), dass die 10 als float betrachtet werden soll und nicht als int.

Danke, wieder was gelernt. 😉

1

Auf der Rechten Seite der Gleichung agiert Du Ausschließlich mit Intergerwerten. (Die Konsrante 10 wird implizit als Integer verwendet und difficulty ist als solcher deklariert. Das Ergebnis ist folglich ein Integer . Dieser Integer wird anschließend an eine float-Variable übergeben und erst zu diesem Zeitpunkt in einen float konvertiert.

Die var-Lösung von @GuteAntwort2021 funktioniert, kann sich jedoch im weiteren Programmverlauf zum Kuckucksei entpuppen:

var difficulty = 4.0;
var timerReset = 10 / (difficulty*difficulty);
 //100 Zeilen später 🤮
float andereVariable=timerReset;

Peng: error CS0266: Der Typ 'double' kann nicht implizit in 'float' konvertiert werden.

(var difficulty = 4.0; und damit auch daraus resultierende Ergebnisse sind implizit ein double und passt nicht (ohne explizite Konvertierung in einen float !)

var sollte man sehr bedacht verwenden.

In diesem Fall würde ich konsequent mit double arbeiten, damit stellst Du sicher, das der Compiler durchgehen code für die Flieskommaeinheiten des Prozessors erzeugt und nich "Unterwegs" Implizite TypUmwandlungen vornehmen muss.

double difficulty = 4;
double timerReset = 10.0 / (difficulty*difficulty);
  //100 Zeilen später!!!
double andereVariable=timerReset;

...so vermeidest Du "Unerwartetes", weil durchgehend klar womit Du arbeiten möchtest.

Palladin007  31.12.2023, 19:00

Hach ja, die schöne Debatte: var Ja oder nein :D

Das Problem, was Du oben skizzierst, tritt ja nur auf, weil Du nicht konsequent var benutzt. Wäre die dritte Variable auch var, gäb's das Problem nicht, dann würde er weiter mit Double rechnen.

Außerdem ist der Fehler ein Compile-Fehler und frisst als solches mMn. keine unnötige Zeit, wie es z.B. bei einem Laufzeit-Fehler der Fall wäre. Man sieht ja sofort, dass es da ein Problem gibt und wer über ein paar Stunden Erfahrung mit C# hinaus ist, hat auch ziemlich schnell eine Vermutung, was das Problem ist und wie man es fixen kann.

Umgekehrt habe ich die Erfahrung gemacht, dass die explizit angegebenen Typen sogar sehr viel häufiger zu unnötigen Compile-Fehlern führen, als das mit var der Fall wäre. Ich habe zu dem Zweck mal ein komplettes Projekt mit dem "kein var"-Ansatz aufgebaut und es hinterher bereut.

Ich denke, die Abneigung zu var rührt eher von anderen Problemen her, die man mit expliziter Typ-Angabe zu kaschieren versucht. In deinem Beispiel wäre das z.B. die Mischung von var und kein var und die Tatsache, dass da 100 Zeilen Code zwischen sein sollen. Wäre die Methode kompakter, wäre auch das Problem sehr viel weniger relevant, da man den Code leicht überblicken kann. Und die Offensichtlichkeit des verwendeten Typs ist mit aussagekräftigen Namen auch nicht mehr so relevant.

1

C# ist klar typisiert. Dadurch hat es eine deutlich schnellere Laufzeit als Scriptsprachen. Allerdings kannst du sowas machen:

var difficulty = 4.0;
var timerReset = 10 / (difficulty*difficulty);

Dann wird das Ergebnis automatisch zu einem double. Wenn du die Variable allerdings mit 4 statt 4.0 deklarierst, wird es eben als int gehandhabt.

Woher ich das weiß:Studium / Ausbildung – Diplom Wirtschaftsinformatiker
Erzesel  31.12.2023, 18:07

So toll die automatische Typisierung mit var auch sein mag, man sollte es wirklich nur verwenden, wenn auf der rechten Seite einer Zuweisung der Typ explizit festgelegt wird. (auch anonyme Typen sind so gesehen explizit als solche festgelegt)

var difficulty = 4.0f;  //rechte seite explizit eine float-Konstante
var xs = new List<int>(); //rechte seite explizit eine Liste von Integern
var v = new { Name="Franz",Age=78 };  ////rechte seite explizit ein Anonymous

...sonst kann var zur "Zeitbombe" werden.

0

weil deine erste variable ein int ist. diese muss auch ein float oder double sein

playToTroll 
Fragesteller
 31.12.2023, 16:09

Das wusste ich tatsächlich nicht, aber demnach vielen Dank, werde es probieren!

0
SnoopCat95  31.12.2023, 16:09
@playToTroll

in python hätte es funktioniert aber in niedrigen sprachen geht sowas nicht

1
GuteAntwort2021  31.12.2023, 16:12
@SnoopCat95

"Niedrigen" Sprachen. Solch einen Kommentar kann man wirklich nur als peinlich deklarieren.

0
Kelec  31.12.2023, 16:42
@GuteAntwort2021

Es ist tatsächlich die Frage hier was man überhaupt als höher definiert.

Im wesentlichen nennt man ja alle Sprachen über Assembler Hochsprachen so ist zB C++ in dem Sinne keine Hochsprache zu C auch wenn es ein Superset ist.

0

Weil alle beiteiligten Operanden (10 und difficulty=4) Ganzzahlen sind, verwendet C# für die Division auch die Ganzzahl-Division (Division ohne Rest). Das Ergebnis ist offensichtlich 0 und wird dann implizit von int nach float gecastet, um in timerReset geschrieben zu werden.

Du könntest entweder einfach direkt 10.0/... schreiben, die Difficulty direkt als float anlegen, vor der Division zu float casten und bestimmt noch Vieles mehr.

Woher ich das weiß:Studium / Ausbildung – Trust me, I'm an engineer